I have an App that has a toolbar at the bottom of the screen and the rest is filled with a custom View (see xml below). Now when I make the App full screen (I tried all possibilities, programmatically and via Manifest.xml), when it's started the whole layout seems to be shifted down by about the height of the notification bar. The buttons in the toolbar are only visible half-way. Sometimes, all of it moves up after a few seconds, or when I click a button in the toolbar.
I'm pretty sure, that it's a problem with my custom view, because I do not get this effect if I replace it with a Button or the like. I guess it must have something to do with the onMeasure
method. I don't really know how to implement it, my version is shown below. The custom view is used for drawing inside, so basically it wants to be as large as possible.
Any help would be much appreciated. I searched for several hours already, but no clue yet.
layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<com.example.MyCanvasView
android:id="@+id/canvas"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
/>
<!-- Buttonbar -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="4dp"
android:orientation="horizontal"
android:background="@android:drawable/bottom_bar"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="3"
/>
</LinearLayout>
</LinearLayout>
And this is my onMeasure
method:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
}
You're not taking the mode into account when you're setting your measurement.
The mode of a MeasureSpec
can be one of MeasureSpec.EXACTLY
, MeasureSpec.AT_MOST
, or MeasureSpec.UNSPECIFIED
. Simply accepting the size component and setting your measured size to that is appropriate for EXACTLY
, but it isn't often the right thing for the others.
Because you're trying to use layout_weight
in addition to a height of wrap_content
on this custom view, the following is happening:
Your custom view is the first child of the LinearLayout with a height of wrap_content
so LinearLayout
measures it. Since LinearLayout
has been told by the LayoutParams
that it should wrap_content
, it measures your custom view with a MeasureSpec
mode of AT_MOST
and a size of the entire available space.
But your custom view is greedy. It decides to take all of the space available. In essence, you have implemented your measurement to treat wrap_content
as match_parent
.
Now there's no more space left. The lower button bar gets measured accordingly but it's not done yet, there's a child with weight. In a LinearLayout
any space left over after all normal measurement is complete is divided among the weighted children according to their weight values. This isn't the behavior you want.
When you use weight to fill available vertical space like you're doing in this layout, you normally want to set the layout_height
to 0dip
. This will make LinearLayout
skip the first measure pass on that child and only use the weighted measurement pass to measure your view, giving it the remaining available space.
I found the reason for the described behaviour. I had set the view to be focusable in touchmode via setFocusableInTouchMode(true)
in the onCreate()
method. As soon as I removed this, it works fine. Thanks to adamp though -- your description of what goes on during layout and measuring was very interesting.
But that leaves me with the problem that I do not receive any key/button clicks any more :-(
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With