1

I want to get the width of a LinearLayout element in my getView method of my custom adapter. My getView method looks like this:

@Override
    public View getView(int position, View v, ViewGroup parent) {
        View mView = v;

        if (mView == null) {

            LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
                    Context.LAYOUT_INFLATER_SERVICE);
            mView = vi.inflate(R.layout.levelselector_item, null);


        } 
if (mView != null) {
...
LinearLayout ln = (LinearLayout) mView.findViewById(R.id.lineScore);
            LinearLayout lnTotal = (LinearLayout) mView.findViewById(R.id.lineScoreTotal);
int widthTotal = lnTotal.getWidth()/2;
                ln.getLayoutParams().height = 3;
                ln.getLayoutParams().width = widthTotal;
                ln.requestLayout();
                ln.setBackgroundColor(Color.parseColor("#eef05e"));

}
        return mView;
    }

The problem my widthTotal doesn't seem to have a value. If I click on an item of the gridview and hit the back button, then I suddenly see a yellow bar. If I enter ln.getLayoutParams().width = 20; he also shows a yellow short bar. I just don't know when or where I can get the width of the LinearLayout...

Jack Commonw
  • 395
  • 6
  • 16

4 Answers4

1

It looks like you are trying to set the dimensions of the lineScore view to be 3 pixels high and half the width of the lineScoreTotal view. Unfortunately, you can't do it like this—the getView code is executed before the view is attached to the activity's view hierarchy, so there is no size defined for anything.

One approach is to define your own custom view and override onMeasure as suggested in this thread. This is perhaps the cleanest way.

Another is to try to query the parent view for its dimensions; account for padding, etc.; and then construct appropriate width and height measure specs and lay out mView before trying to query for the dimensions.

Another is to create a layout that divides up the total width into the desired proportions. Since you haven't posted your layout, I can't suggest anything specific. If the container for the row is a vertical LinearLayout, for instance, you could do something like this::

<LinearLayout
     android:orientation="vertical"
     . . . >
     . . .
    <LinearLayout
         android:orientation="horizontal"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content">

         <View
              android:layout_width="0dp"
              android:layout_height="3dp"
              android:layout_weight="25" />
         <View
              android:layout_width="0dp"
              android:layout_height="3dp"
              android:layout_weight="50"
              android:background="#eef05e" />
         <View
              android:layout_width="0dp"
              android:layout_height="3dp"
              android:layout_weight="25" />
    </LinearLayout>
    . . .
</LinearLayout>

This is not particularly efficient (using three extra views), but it lets you do everything in XML. If you are targeting API level 14 or above, you can also use the Space view to provide spacing.

EDIT

Here's code that outlines what I mean by "query the parent view...":

int availW = parent.getWidth() - parent.getPaddingLeft() - parent.getPaddingRight();
int widthSpec = MeasureSpec.makeMeasureSpec(availW, MeasureSpec.AT_MOST);
// similar for height
mView.measure(widthSpec, heightSpec);
mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
// now you can query the width of `mView`

I have not tested this, so I can't warrant that it will work, but this is the idea.

Community
  • 1
  • 1
Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • What do you mean exact with query the parent view for its dimensions? What I do know, is that the width of the linearlayout = mView.getWidth - (2*20dp), but I dont know if I can go from dp to px? Maybe that is also a solution (or maybe you ment that? :)) – Jack Commonw Oct 03 '12 at 17:21
  • @JackCommonw - I was referring to the third argument passed to `getView`. This is the view that will become the parent to the view that `getView` returns. – Ted Hopp Oct 03 '12 at 17:22
  • I'm sorry, but I still don't know what you mean by "querying the parent view for its dimensions" and to layout the mView with proper width and height specs... can you explain a little bit more about this? Do you think my solution above could work? – Jack Commonw Oct 03 '12 at 17:28
  • I tried this: int test = mView.getWidth(); Resources r = C.getResources(); float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, r.getDisplayMetrics()); int submit = (test - (2*(int)px))/2; But then I get an error. I'll try your method – Jack Commonw Oct 03 '12 at 18:10
  • @JackCommonw - The easiest thing is to define your own custom view that lays itself out appropriately (or, better yet, just draws appropriately). – Ted Hopp Oct 03 '12 at 19:43
  • Ok, is it possible to pass a variable width to this custom view then? Its just my first app and never made a custom view before.. Maybe you know a good tutorial on this? Thanks! – Jack Commonw Oct 03 '12 at 20:42
1

Instead of setting the dimensions in code you can do it in XML. You can use LinearLayout weight property to get "half" parent width. e.g.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:weightSum="2" >

    <View
        android:layout_width="0dp"
        android:layout_height="3dp"
        android:layout_weight="1"
        android:background="#eef05e" />

</LinearLayout>
Sameer
  • 4,379
  • 1
  • 23
  • 23
  • The width is dynamic... Not in my example but it will be based on the width of the LL – Jack Commonw Oct 03 '12 at 18:09
  • you mean width need not be half of the parent width? In that case you can set the weight in code. – Sameer Oct 03 '12 at 18:29
  • No I just divided it by 2 in this example, but actually it will be (anothervalue / the totalwidth which I need to retrieve ) * 100.. I can't get it to work... still not – Jack Commonw Oct 03 '12 at 18:48
  • 1
    I assume you know what percentage or fraction of parent width you need. Define the weightSum on the parent, to say 100. And set the weight of the child in code after you inflate the XML, to that percentage value. – Sameer Oct 04 '12 at 02:13
  • Well what does the parent exactly tell me? I know that comparing to the eventual view of the item in the gridview, the width of the bar (the linearlayout I am using right now) will be starting from the left (left margin = 20dp) and can have a maximum until it reaches a margin to the right of 20dp. – Jack Commonw Oct 04 '12 at 09:29
0

I don't think you can get the width of the view before you set the layout(R.layout.levelselector_item ) on the screen. It should return 0.

rahul
  • 6,447
  • 3
  • 31
  • 42
  • How do you mean? The R.layout.levelselector_item is called: if (mView == null) { LayoutInflater vi = (LayoutInflater) getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); mView = vi.inflate(R.layout.levelselector_item, null); } Or maybe there is another way to go around this problem.. ? – Jack Commonw Oct 03 '12 at 17:06
0

I got it to work properly. For those who might be interested:

I first set my border around my gridview to an amount which is controlable by adding to my gridview in xml:

android:listSelector="@null"
android:layout_margin="5dp"

Then I used a combination of Ted Hopp's and Sameer's solution: Since I know what the padding of my elements is; 5dp around the gridview, 2dp between the elements and 15dp in an element. I also have 3 items each row, this makes my code look like:

int parentW = parent.getWidth() - parent.getPaddingLeft() - parent.getPaddingRight();
                Resources r = C.getResources();
                float pxPaddingBetweenItem = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, r.getDisplayMetrics());
                float pxPaddingInItem = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, r.getDisplayMetrics());

                int totalBarWidth = (parentW - (int)(2*pxPaddingBetweenItem)  - (int)(6*pxPaddingInItem))/3;

And this takes me exactly where I want to be :) Thanks!

Jack Commonw
  • 395
  • 6
  • 16