Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create two views in Android that use 50% height each, unless one is smaller?

Imagine a full Android device screen, I want it split in to two sections:

  1. The upper half has text in it, which may be larger than the space available (or not) and so the text will scroll (i.e. TextView inside a ScrollView)
  2. The lower half contains a MapView control.

Looking specifically at some scenarios:

  1. If the text is small, I want the map to take up more space, i.e. more than 50%. So perhaps 20% text, 80% map.
  2. If the text is larger, it only takes up a MAXIMUM of 50% of the screen space, and then scrolls. So 50% map, 50% text.

At the moment I've assigned weights to the two parts, and that isn't too bad, but if the text is small, the map doesn't expand to take the space, and the layout has a wasted gap that the map could usefully use.

I've tried loads of combinations but can't see how to make this happen. It seems to be a common experience for me that I know what I want, but can't see how to get the available views to deliver it. I'm hoping there's a nice easy way to do this.

Please feel free to make me look like a fool and point out the obvious attribute I've missed :-)

======================================================================

As far as I can see there's no way to do this just in declarative XML and it needs doing in the code. I set the text section height to wrap_content, weight to 0 (no resizing), and have the map set to weight=1 (i.e. take up the remaining space). I then check if the text section (in a ScrollView) is taking up too much space and if so, shrink it back. This code would need changing to support a different layout orientation.

private void fixLayoutProportions()
{
    float maxPercentageOfScreenForText = 50/100;
    LinearLayout container = (LinearLayout)findViewById(R.id.container);
    ScrollView eventText = (ScrollView)findViewById(R.id.text_scroller);
    int heightAvailable = container.getHeight();
    int scrollerHeight = eventText.getHeight();
    if ( scrollerHeight>(heightAvailable*maxPercentageOfScreenForText) )      // Text section using too much space
    {
        eventText.getLayoutParams().height = (int)(heightAvailable*maxPercentageOfScreenForText) ;
        eventText.invalidate();
    }
}
like image 477
Ollie C Avatar asked Nov 30 '10 15:11

Ollie C


People also ask

How can get device height and width in android programmatically?

Display display = getWindowManager(). getDefaultDisplay(); Point size = new Point(); display. getSize(size); int width = size. x; int height = size.

How do I move one view to the top of another Android?

Just in case if you want to place a view on top of a ButtonView then use this; android:elevation="7dp" for the view which needs to be placed on top of the button. Thanks. It worked, but also worked with 1dp up for me.

Can we use linear layout in ConstraintLayout?

You can create linear layouts now with ConstraintLayout by constraining the sides of each element with each other. The quick way of creating these layouts is to select all the views together and right click to center horizontally or vertically.


3 Answers

You can do it by putting everything into LinearLayout and changing following parameters:

  • the sum of weights for LienarLayout
  • weights for children
like image 93
Damian Kołakowski Avatar answered Oct 12 '22 19:10

Damian Kołakowski


Did you try to measure your screen hight at run time:

Display display = ((WindowManager) 
      getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); 
int width = display.getHeight();

Then, set your top view max_height to width*0.5 and min_height to width*0.2. Your top view has to be control (like TextView) that has min_height and max_height properties. Also, set layout_weight to 0 or leave it empty. On your bottom view set layout weight to 1.

like image 28
bobetko Avatar answered Oct 12 '22 19:10

bobetko


The easiest way to do 50/50 is in XML is using LinearLayout weights. Basically put the two views into a single LinearLayout set the android:layout_weight on both child views to the same value, like setting both to .5, 1, or 42. You then set the layout_width to 0px or fill_parent/match_parent.

The smaller part gets more complicated. Luckily, you can turn off weighing in Java. One way is to wait until the windows get drawn (if they are pre-populated) and measure them. This can be done on I think it was called onWindowFocusChanged

like image 22
Joe Plante Avatar answered Oct 12 '22 18:10

Joe Plante