Android: можно ли установить высоту SlidingDrawer с помощью содержимого wrap?
Я пытаюсь реализовать SlidingDrawer который будет занимать всю ширину экрана, но высота которого определяется динамически его содержимым: другими словами, стандартный fill_parent поведение макета для ширины и wrap_content для высоты. Именно так я указал его в XML-макете (см. ниже), но выдвижной ящик всегда открывается на всю высоту экрана. Высота моего контента варьируется, но обычно это только половина высоты экрана, поэтому я получаю большой зазор внизу оно. Я бы хотел, чтобы контент аккуратно сидел в нижней части экрана.
Я пробовал все, что я могу придумать, чтобы это исправить, но ничего не работает до сих пор. Если я установил SlidingDrawer ' s 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>
6 ответов:
The
onMeasure()метод класса SlidingDrawer в основном переопределяет режимы компоновки наfill_parent, поэтомуlayout_height="wrap_content"не работает.чтобы обойти это, вы можете расширить SlidingDrawer с повторно реализованной
onMeasure()метод, который чтитlayout_widthиlayout_heightатрибуты. Затем вы можете использовать этот пользовательский класс в XML-макета, заменив<SlidingDrawer ...>С<fully.qualified.package.ClassName ...>.обратите внимание, что поскольку ящик больше не будет заполнять Родительский макет, у вас будет чтобы заключить его в 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.пакет) :
<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>
У ответа Сейда есть небольшая проблема.
первым аргументом 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);еще один issus находится в 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> ...
Comments