全画面幅を占めるSlidingDrawer
を実装しようとしていますが、その高さはその内容によって動的に決定されます。つまり、幅の場合は標準のfill_parent
レイアウト動作、高さの場合はwrap_content
です。それはまさにレイアウトXML(下記参照)で指定した方法ですが、スライド式引き出しは常に全画面の高さまで開きます。コンテンツの高さはさまざまですが、通常は画面の高さの約半分しかないため、その下に大きな隙間ができます。コンテンツが画面の下部にきちんと収まるようにしたいです。
私はそれを修正するために考えることができるすべてを試してみましたが、今のところ何も機能していません。 SlidingDrawer
のlayout_height
を特定の値(たとえば、160dip
)に設定した場合、それは機能しますが、それは必要ではありません。動的でなければなりません。もちろん、すべての子要素の高さもwrap_content
に設定されていることを確認しました。
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>
SlidingDrawerクラスのonMeasure()
メソッドは、基本的にレイアウトモードを_fill_parent
_にオーバーライドします。これが_layout_height="wrap_content"
_が機能しない理由です。
これを回避するには、_layout_width
_および_layout_height
_属性を尊重する再実装されたonMeasure()
メソッドでSlidingDrawerを拡張できます。その後、_<SlidingDrawer ...>
_を_<fully.qualified.package.ClassName ...>
_に置き換えることにより、XMLレイアウトでこのカスタムクラスを使用できます。
ドロワーは親レイアウトを埋めないため、引出しがあるべきEdgeに設定された重力属性を持つLinearLayoutでドロワーを囲む必要があることに注意してください。
以下は、この目的のために作成したクラスとレイアウトの例です。
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>
_
あなたのXMLのスライド引き出しでpmarginに設定するだけです
Android:layout_marginTop="50dip"
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);
水平方向のスライドドロワーでこれを機能させるのに問題がありましたが、それが方向属性を見つけられず、それを垂直として扱っていたことがわかりました。
文字列をハードコーディングせずにパラメーターを読み取ることをお勧めします。
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();
}
残念ながら、高さを設定することはできませんが、その反対です。 topOffset属性は、スライド式引き出しの高さを決定しますが、その高さではなく、何を削るかを決定します。
わたしにはできる:
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="<"
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>
...