Android: Can Height of Slidingdrawer Be Set with Wrap_Content

Android: can height of SlidingDrawer be set with wrap_content?

The onMeasure() method of the SlidingDrawer class basically overrides the layout modes to fill_parent, this is why layout_height="wrap_content" is not working.

To get around this, you can extend SlidingDrawer with a re-implemented onMeasure() method that honors the layout_width and layout_height attributes. You can then use this custom class in your XML layout by replacing <SlidingDrawer ...> with <fully.qualified.package.ClassName ...>.

Note that since the drawer will no longer be filling the parent layout, you will have to enclose it in a LinearLayout with the gravity attribute set to the edge where the drawer should be.

Below are a class I have created for this purpose and an example layout.

WrappingSlidingDrawer class :

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.SlidingDrawer;

public class WrappingSlidingDrawer extends SlidingDrawer {

public WrappingSlidingDrawer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);

int orientation = attrs.getAttributeIntValue("android", "orientation", ORIENTATION_VERTICAL);
mTopOffset = attrs.getAttributeIntValue("android", "topOffset", 0);
mVertical = (orientation == SlidingDrawer.ORIENTATION_VERTICAL);
}

public WrappingSlidingDrawer(Context context, AttributeSet attrs) {
super(context, attrs);

int orientation = attrs.getAttributeIntValue("android", "orientation", ORIENTATION_VERTICAL);
mTopOffset = attrs.getAttributeIntValue("android", "topOffset", 0);
mVertical = (orientation == SlidingDrawer.ORIENTATION_VERTICAL);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);

int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);

if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) {
throw new RuntimeException("SlidingDrawer cannot have UNSPECIFIED dimensions");
}

final View handle = getHandle();
final View content = getContent();
measureChild(handle, widthMeasureSpec, heightMeasureSpec);

if (mVertical) {
int height = heightSpecSize - handle.getMeasuredHeight() - mTopOffset;
content.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, heightSpecMode));
heightSpecSize = handle.getMeasuredHeight() + mTopOffset + content.getMeasuredHeight();
widthSpecSize = content.getMeasuredWidth();
if (handle.getMeasuredWidth() > widthSpecSize) widthSpecSize = handle.getMeasuredWidth();
}
else {
int width = widthSpecSize - handle.getMeasuredWidth() - mTopOffset;
getContent().measure(MeasureSpec.makeMeasureSpec(width, widthSpecMode), heightMeasureSpec);
widthSpecSize = handle.getMeasuredWidth() + mTopOffset + content.getMeasuredWidth();
heightSpecSize = content.getMeasuredHeight();
if (handle.getMeasuredHeight() > heightSpecSize) heightSpecSize = handle.getMeasuredHeight();
}

setMeasuredDimension(widthSpecSize, heightSpecSize);
}

private boolean mVertical;
private int mTopOffset;
}

Example layout (assuming WrappingSlidingDrawer is in package com.package) :

<FrameLayout android:layout_width="fill_parent"
android:layout_height="fill_parent">
... stuff you want to cover at full-size ...
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="bottom"
android:orientation="vertical">
<com.package.WrappingSlidingDrawer android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:content="@+id/content"
android:handle="@+id/handle">
... handle and content views ...
</com.package.WrappingSlidingDrawer>
</LinearLayout>
</FrameLayout>

How to set height of SlidingDrawer through XML?

The onMeasure() method of the SlidingDrawer class basically overrides the layout modes to fill_parent, this is why layout_height="wrap_content" is not working.

To get around this, you can extend SlidingDrawer with a re-implemented onMeasure() method that honors the layout_width and layout_height attributes. You can then use this custom class in your XML layout by replacing with .

Note that since the drawer will no longer be filling the parent layout, you will have to enclose it in a LinearLayout with the gravity attribute set to the edge where the drawer should be.

the Answer

your Question

set sliding drawer height dynamically

You can set the height to a specific height such as 200dp, or you can use something like this workaround if you want to use wrap_content.

Android : is there a way to properly set a SlidingDrawer width and height to half screen?

Its always better to put the sliding drawer in a frame layout. Because in Framelayout, views will be drawn one on the other. Then even even you drawer opens up it 'll be overlapped on the views beneath. But note that in Framelayout drawer expands up to all the framelayout length. If you want to limit the length of expansion of the drawer, then give a length to your parent framelayout.

How can i limit the size of a sliding drawer?

This answer about overriding SlidingDrawer#onMeasure to enable wrap_content for SlidingDrawer seems like a winner.

The onMeasure() method of the
SlidingDrawer class basically
overrides the layout modes to
fill_parent, this is why
layout_height="wrap_content" is not
working.

Edit - Or, you can set the height exactly in with something like layout_height="200dp".

Your other question was already answered in the negative.

SlidingDrawer cannot have UNSPECIFIED dimensions

I was having the same issue so I went digging in the source code. The basic answer is that something called measure() on your SlidingDrawer using MeasureSpec.UNSPECIFIED, i.e. the SlidingDrawer is allowed to set its own size.

It could be caused by the containing layout (or its parents) being base-aligned or having WRAP_CONTENT as its height or width. If the containing LinearLayout has baselineAligned set true, it asks all its children for their size to find the largest one. And of course it also asks its children for their size if it's supposed to wrap them.

Set android:baselineAligned="false" in any LinearLayout that contains the sliding drawer and ensure that nothing containing the SlidingDrawer has WRAP_CONTENT for height or width. In other words, the SlidingDrawer must have an exact size defined, which means its parents must also if you use FILL_PARENT.



Related Topics



Leave a reply



Submit