Android:可以使用 wrap_content 设置 SlidingDrawer 的高度吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3654492/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android: can height of SlidingDrawer be set with wrap_content?
提问by Mark Whitaker
I'm trying to implement a SlidingDrawer
that will occupy the full screen width, but whose height is determined dynamically by its contents: in other words, standard fill_parent
layout behaviour for the width and wrap_content
for the height. That's exactly how I've specified it in the layout XML (see below) but the sliding drawer always opens to the full screen height. The height of my content varies, but typically it's only about half the screen height, so I end up with a big gap underneath it. What I'd like is for the content to sit neatly on the bottom of the screen.
我正在尝试实现一个SlidingDrawer
将占据整个屏幕宽度,但其高度由其内容动态确定的:换句话说,fill_parent
宽度和wrap_content
高度的标准布局行为。这正是我在布局 XML 中指定的方式(见下文),但滑动抽屉始终打开至全屏高度。我的内容的高度各不相同,但通常只有屏幕高度的一半左右,所以我最终在它下面有一个很大的间隙。我想要的是内容整齐地放在屏幕底部。
I've tried everything I can think of to fix it but nothing's worked so far. If I set the SlidingDrawer
's layout_height
to a specific value (e.g. 160dip
) it works, but that's not what I need: it has to be dynamic. Of course I've made sure all the child elements have their height set to wrap_content
too.
我已经尝试了所有我能想到的方法来修复它,但到目前为止没有任何效果。如果我将SlidingDrawer
'slayout_height
设置为特定值(例如160dip
),它可以工作,但这不是我需要的:它必须是动态的。当然,我已经确保所有子元素的高度也设置为wrap_content
。
The documentation on SlidingDrawer is a bit vague on this and I haven't been able to find any examples that do what I'm after either. If anyone can see where I'm going wrong I'd really appreciate your help!
SlidingDrawer 上的文档对此有点含糊,我也找不到任何可以实现我所追求的示例。如果有人能看到我哪里出错了,我将非常感谢您的帮助!
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ViewFlipper
android:id="@+id/ImageFlipper"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="@+id/imageView0"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="centerCrop" />
<ImageView
android:id="@+id/imageView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="centerCrop" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="centerCrop" />
</ViewFlipper>
<SlidingDrawer
android:id="@+id/infoDrawer"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:handle="@+id/infoDrawerHandle"
android:content="@+id/infoDrawerContent"
android:allowSingleTap="false"
android:layout_alignParentBottom="true"
android:orientation="vertical" >
<!-- Sliding drawer handle -->
<ImageView
android:id="@id/infoDrawerHandle"
android:src="@drawable/info_handle_closed"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- Sliding drawer content: a scroller containing a group of text views
laid out in a LinearLayout -->
<ScrollView
android:id="@id/infoDrawerContent"
android:background="@drawable/info_background"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fillViewport="false" >
<LinearLayout
android:id="@id/infoDrawerContent"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="5dip" >
<TextView
android:id="@+id/infoTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:textSize="16dip"
android:textStyle="bold" />
<TextView
android:id="@+id/infoCreator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:textSize="14dip"
android:textStyle="italic"
android:paddingBottom="10dip" />
<TextView
android:id="@+id/infoDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:textSize="14dip"
android:paddingBottom="10dip" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffcc00"
android:textSize="14dip"
android:textStyle="bold"
android:text="@string/heading_pro_tip" />
<TextView
android:id="@+id/infoProTip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffcc00"
android:textSize="14dip" />
</LinearLayout>
</ScrollView>
</SlidingDrawer>
</RelativeLayout>
回答by seydhe
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.
onMeasure()
SlidingDrawer 类的方法基本上将布局模式覆盖为fill_parent
,这就是为什么layout_height="wrap_content"
不起作用。
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 ...>
.
为了解决这个问题,您可以使用重新实现的onMeasure()
方法来扩展 SlidingDrawer,该方法尊重layout_width
和layout_height
属性。然后,您可以通过替换<SlidingDrawer ...>
为.xml 来在 XML 布局中使用此自定义类<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.
请注意,由于抽屉将不再填充父布局,因此您必须将其包含在 LinearLayout 中,并将重力属性设置为抽屉应位于的边缘。
Below are a class I have created for this purpose and an example layout.
下面是我为此目的创建的一个类和一个示例布局。
WrappingSlidingDrawer class :
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;
}
Example layout (assuming WrappingSlidingDrawer is in package com.package) :
示例布局(假设 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>
回答by A B
just set to pmargin in sliding drawer in your xml
只需在 xml 的滑动抽屉中设置为 pmargin
android:layout_marginTop="50dip"
回答by museofwater
seydhe's answer has a small issue.
赛德的回答有一个小问题。
The first argument to the getAttributeIntValue needs to be the full namespace, not just "android". So the code snippet should be:
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);
I was having trouble getting this to work with a horizontal sliding drawer until I realized that it was not finding the orientation attribute and was therefore treating it as vertical.
我很难让它与水平滑动抽屉一起工作,直到我意识到它没有找到方向属性,因此将其视为垂直。
回答by kingston
it is better to read the parameter without hardcoding the string:
最好在不对字符串进行硬编码的情况下读取参数:
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);
Another issus is in the onMeasure.
另一个问题是在 onMeasure 中。
I used the following code:
我使用了以下代码:
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();
}
回答by Nathan Schwermann
unfortunately you can't set the height, but rather the opposite of that. the topOffset attribute will determine how tall to make the sliding drawer, but its what to shave off rather than how tall it will be.
不幸的是你不能设置高度,而是相反。topOffset 属性将决定滑动抽屉的高度,但它决定要剃掉的东西而不是它的高度。
回答by Alex K
It works for me:
这个对我有用:
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 Layout:
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="<"
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>
...