1

I have 5 LinearLayouts. For ease of writing and understanding, I'll refer to them as Views A - E.

View A is the parent of Views B, C, D, and E.

I have set the layout_weight to 8.0f for View A and the weights to 1.0f, 3.0f, 1.0f, 3.0f for Views B - E respectively.

I understand that this is for managing the empty space in the parent view, but I was hoping to size my View and subviews to own a percentage of the screen, rather than compete just for the free space.

However, this is all done programmatically, so should I set the height of the LinearLayouts to a coefficient of the getHeight() method/accessor of it's parent (View A)? If so, then how can I get the height of the parent if the view hasn't yet been added to it's parent, which would set its height with MATCH_PARENT?

Since the getHeight() method will return 0 for onCreate, onStart, and the first onResume, I had to keep looking for an answer. I found ViewTreeObserver and OnGlobalLayoutListener, which will let me know when the Layouts have been set. However, I would really appreciate having the height before any drawing occurs. Is that not possible?

double-beep
  • 5,031
  • 17
  • 33
  • 41
RileyE
  • 10,874
  • 13
  • 63
  • 106
  • I have successfully taken the measure of the screen in onViewCreated in a fragment. So you could fill parent with the fragment, then draw your layout in the fragment. – anthropomo Jan 25 '13 at 00:43

3 Answers3

2

If you don't need to do this programatically, you can do it in xml. In order to have the child LinearLayouts take up a percentage of the Parent LinearLayout (LinearLayout A) then you need to set the parent's weightSum=(Total layout_weight of child LinearLayouts) and then set the child LinearLayouts width/height property to "0dip" and set their layout_weight to the desired percentage.

Sample code for a vertical orientation would be:

<LinearLayout
     android:id="@+id/A"
     android:layout_height="fill_parent"
     android:layout_width="fill_parent"
     android:weightSum="8.0"
     android:orientation="vertical">
     <LinearLayout
          android:id="@+id/B"
          android:layout_height="0dip"
          android:layout_width="fill_parent"
          android:layout_weight="1.0"/>
     <LinearLayout
          android:id="@+id/C"
          android:layout_height="0dip"
          android:layout_width="fill_parent"
          android:layout_weight="3.0"
</LinearLayout>
  • I've done that programmatically, other than setting the height in LayoutParams to 0dp. I'll have to try that and get back to you on that, because it's only adjusting the free space, rather than the total space. – RileyE Jan 25 '13 at 02:12
  • This is usually how you would create a layout that expands based on percentages. [Referenced here](http://stackoverflow.com/questions/4986861/android-layout-weight/4987097#4987097) – John Thompson Jan 25 '13 at 04:22
  • Wow. So, the difference was exactly that I needed to set the height to 0, versus wrap_content. Thanks! – RileyE Jan 25 '13 at 19:53
1

Unfortunately, it's not possible to get the size of a view before it's drawn (not unless there is a hack out there that I'm unaware of). The view doesn't hold any information about its size until it until it is ready to be laid out. It would be nice if, in a future release, they designed the system hold the view dimensions prior to the view being drawn.

You could create a custom class, extend the View class, and then override a method that is called by the system and return the dimensions to an object reference in your activity. However, this is likely to be more of a headache then a help and doesn't really give you any real advantage.

I'd recommend using ViewTreeObserver and the OnGlobalLayoutListener.

Don
  • 506
  • 2
  • 8
  • 23
  • Okay, well, I will have to try out all three answers and see what performs the best. They all sound like there may be some drawing issues when the view is appearing. Fingers crossed! – RileyE Jan 25 '13 at 02:16
1

Here's how to do this with Fragments as mentioned above.

First save a reference to context in the onAttach method (you will probably want to setup a callback to the activity anyway:

Context context;

@Override
public void onAttach(Activity activity){
    super.onAttach(activity);

    context = activity;


} 

Then in onViewCreate, you take the measurements and use them:

public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    Display display = ((WindowManager)
        context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
    DisplayMetrics metrics = new DisplayMetrics();
    display.getMetrics(metrics);

    float pixHeight = metrics.heightPixels;
    float pixWidth = metrics.widthPixels;
    float density  = context.getResources().getDisplayMetrics().density;
    float dpHeight = pixHeight / density;
    float dpWidth  = pixWidth / density;

    // make various layouts using your measurements, send the
    // measure of each parent to each custom drawn child, or 
    // send the bounds of each child as determined by the size of each parent

    return someView;
}
anthropomo
  • 4,100
  • 1
  • 24
  • 39
  • Thanks for the answer! I will have to try everything out and see what performs the best, since there is a lot of drawing to do in a small amount of time. – RileyE Jan 25 '13 at 02:15
  • Might be a good idea to pass measurements in one of these: http://developer.android.com/reference/android/graphics/RectF.html – anthropomo Jan 25 '13 at 02:17
  • Thats a great reference, however it will slow down the performance, since it is an `Object` subclass, rather than a primitive data type. I only need to pass a height parameter, but thank you for the link! :) – RileyE Jan 25 '13 at 15:45
  • When I do custom drawing, I send bounds to each child that will need to draw itself (I use a lighter weight object than RectF). Are you sure you aren't prematurely optimizing? If you're really worried about speed, it is my understanding that LinearLayout is resource hungry, and if you can get by with a Relative or Frame in some cases, it is for the better. – anthropomo Jan 25 '13 at 17:38
  • Oh? Relative layout is more efficient? I can partially switch to those. But this is definitely not prematurely optimizing, since I have to handle the view creation inside the draw methods. I want the app to be as smooth as possible. Maybe I'm misunderstanding what you mean by prematurely optimizing. – RileyE Jan 25 '13 at 18:53