Android:可以用wrap_content设置SlidingDrawer的高度吗?

时间:2010-09-06 21:53:29

标签: android layout slidingdrawer

我正在尝试实现占用整个屏幕宽度的SlidingDrawer,但其高度由其内容动态确定:换句话说,宽度的标准fill_parent布局行为和{ {1}}为高度。这正是我在布局XML中指定它的方式(见下文),但滑动抽屉始终打开到全屏高度。我的内容高度各不相同,但通常它只有屏幕高度的一半左右,所以我最终会在它下面留下一个很大的空隙。我想要的是将内容整齐地放在屏幕的底部。

我已经尝试了所有我能想到的东西来解决它但到目前为止没有任何工作。如果我将wrap_content的{​​{1}}设置为特定值(例如SlidingDrawer),则可行,但这不是我需要的:它必须是动态的。当然,我已经确保所有子元素的高度也设置为layout_height

关于SlidingDrawer的文档在这方面有点模糊,我无法找到任何能够完成我所做的事情的例子。如果有人能看到我出错的地方,我真的很感谢你的帮助!

160dip

6 个答案:

答案 0 :(得分:126)

SlidingDrawer类的onMeasure()方法基本上覆盖了fill_parent的布局模式,这就是layout_height="wrap_content"无效的原因。

要解决此问题,您可以使用重新实现的onMeasure()方法扩展SlidingDrawer,以尊重layout_widthlayout_height属性。然后,您可以将<SlidingDrawer ...>替换为<fully.qualified.package.ClassName ...>

,在XML布局中使用此自定义类

请注意,由于抽屉将不再填充父版面,因此您必须将其包含在LinearLayout中,并将gravity属性设置为抽屉所在的边缘。

下面是我为此目的创建的一个类和一个示例布局。

WrappingSlidingDrawer类:

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;
}

示例布局(假设WrappingSlidingDrawer在包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>

答案 1 :(得分:5)

在xml的滑动抽屉中设置为pmargin

android:layout_marginTop="50dip"

答案 2 :(得分:5)

seydhe的答案有一个小问题。

getAttributeIntValue的第一个参数需要是完整的命名空间,而不仅仅是“android”。所以代码片段应为:

final String xmlns="http://schemas.android.com/apk/res/android";
int orientation = attrs.getAttributeIntValue(xmlns, "orientation", SlidingDrawer.ORIENTATION_VERTICAL);
 mTopOffset = attrs.getAttributeIntValue(xmlns, "topOffset", 0);

我无法使用水平滑动抽屉,直到我意识到它没有找到方向属性,因此将其视为垂直滑动。

答案 3 :(得分:4)

最好在不对字符串进行硬编码的情况下读取参数:

    int attrOrientation = android.R.attr.orientation;
    int attrTopOffset = android.R.attr.topOffset;

    int[] attrIds = new int [] {attrOrientation, attrTopOffset}; 

    TypedArray a = context.obtainStyledAttributes(attrs, attrIds);
    int orientation = a.getInt(0, SlidingDrawer.ORIENTATION_VERTICAL);
    topOffset = a.getDimension(1, 0);
    a.recycle(); 

    isVertical = (orientation == SlidingDrawer.ORIENTATION_VERTICAL);

另一个问题在于onMeasure。

我使用了以下代码:

    if (isVertical) {
        int height = heightSpecSize - handle.getMeasuredHeight() - topOffset;
        getContent().measure(MeasureSpec.makeMeasureSpec(widthSpecSize, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
        heightSpecSize = handle.getMeasuredHeight() + topOffset + content.getMeasuredHeight();
        widthSpecSize = content.getMeasuredWidth();
        if (handle.getMeasuredWidth() > widthSpecSize) widthSpecSize = handle.getMeasuredWidth();
    } else {
        int width = widthSpecSize - handle.getMeasuredWidth() - topOffset;
        getContent().measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(heightSpecSize, MeasureSpec.UNSPECIFIED));
        widthSpecSize = handle.getMeasuredWidth() + topOffset + content.getMeasuredWidth();
        heightSpecSize = content.getMeasuredHeight();
        if (handle.getMeasuredHeight() > heightSpecSize) heightSpecSize = handle.getMeasuredHeight();
    }

答案 4 :(得分:2)

不幸的是你不能设置高度,而是相反。 topOffset属性将决定制作滑动抽屉的高度,但要确定刮掉的高度而不是高度。

答案 5 :(得分:0)

它对我有用:

private SlidingDrawer rightSlidingPanel = null;

 @Override 
public void onCreate( Bundle savedInstanceState )
{
...
    rightSlidingPanel = (SlidingDrawer) findViewById( R.id.rightSlidingPanel );
    rightSlidingPanel.post( new Runnable() 
            {
                @Override
                public void run()
                {
                    rightSlidingPanel.getLayoutParams().width = findViewById( R.id.sliding_content2 ).getMeasuredWidth() + findViewById( R.id.sliding_handle ).getMeasuredWidth();
                }

            });
}

XML布局:

...
    <SlidingDrawer
            android:id="@+id/rightSlidingPanel"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:allowSingleTap="true"
            android:animateOnClick="true"
            android:content="@+id/sliding_content"
            android:handle="@+id/sliding_handle"
            android:orientation="horizontal" >

            <Button
                android:id="@+id/sliding_handle"
                style="@style/toolbar_button"
                android:layout_width="30dp"
                android:layout_height="wrap_content"
                android:height="40dp"
                android:text="&lt;"
                android:width="25dp" />

            <LinearLayout
                android:id="@+id/sliding_content"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="top"
                android:orientation="vertical" >

                <LinearLayout
                    android:id="@+id/sliding_content2"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_gravity="center_vertical"
                    android:layout_weight="1"
                    android:gravity="center_horizontal" >

...
                </LinearLayout>
            </LinearLayout>
        </SlidingDrawer>
...