Android: la hauteur de SlidingDrawer peut-elle être définie avec wrap_content?

J’essaie d’implémenter un SlidingDrawer qui occupera toute la largeur de l’écran, mais dont la hauteur est déterminée dynamicment par son contenu: en d’autres termes, le comportement de mise en page standard fill_parent pour la largeur et wrap_content pour la hauteur. C’est exactement ce que j’ai spécifié dans le XML de mise en page (voir ci-dessous), mais le tiroir coulissant s’ouvre toujours à la hauteur totale de l’écran. La hauteur de mon contenu varie, mais en général, la hauteur de l’écran n’est que la moitié moins élevée. Ce que j’aimerais, c’est que le contenu soit bien placé au bas de l’écran.

J’ai essayé tout ce dont je pouvais penser pour y remédier, mais rien n’a fonctionné jusqu’à présent. Si je règle le SlidingDrawer du layout_height sur une valeur spécifique (par exemple 160dip ), cela fonctionne, mais ce n’est pas ce dont j’ai besoin: il doit être dynamic. Bien sûr, je me suis assuré que tous les éléments enfants ont leur hauteur définie sur wrap_content .

La documentation sur SlidingDrawer est un peu vague à ce sujet et je n’ai pas été en mesure de trouver des exemples qui font ce que je suis non plus. Si quelqu’un peut voir où je me trompe, j’apprécierais vraiment votre aide!

                      

La méthode onMeasure() de la classe SlidingDrawer remplace essentiellement les modes de fill_parent avec fill_parent , c’est pourquoi layout_height="wrap_content" ne fonctionne pas.

Pour contourner ce problème, vous pouvez étendre SlidingDrawer avec une méthode onMeasure() ré-implémentée qui layout_height atsortingbuts layout_width et layout_height . Vous pouvez ensuite utiliser cette classe personnalisée dans votre mise en page XML en remplaçant par .

Notez que puisque le tiroir ne remplira plus la mise en page parente, vous devrez le placer dans un LinearLayout avec l’atsortingbut de gravité défini sur le bord du tiroir.

Vous trouverez ci-dessous une classe que j’ai créée à cet effet et un exemple de disposition.

Classe WrappingSlidingDrawer:

 import android.content.Context; import android.util.AtsortingbuteSet; import android.view.View; import android.widget.SlidingDrawer; public class WrappingSlidingDrawer extends SlidingDrawer { public WrappingSlidingDrawer(Context context, AtsortingbuteSet attrs, int defStyle) { super(context, attrs, defStyle); int orientation = attrs.getAtsortingbuteIntValue("android", "orientation", ORIENTATION_VERTICAL); mTopOffset = attrs.getAtsortingbuteIntValue("android", "topOffset", 0); mVertical = (orientation == SlidingDrawer.ORIENTATION_VERTICAL); } public WrappingSlidingDrawer(Context context, AtsortingbuteSet attrs) { super(context, attrs); int orientation = attrs.getAtsortingbuteIntValue("android", "orientation", ORIENTATION_VERTICAL); mTopOffset = attrs.getAtsortingbuteIntValue("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; } 

Exemple de disposition (en supposant que WrappingSlidingDrawer se trouve dans le package com.package):

  ... stuff you want to cover at full-size ...   ... handle and content views ...    

il suffit de définir sur pmargin dans le tiroir coulissant dans votre xml

 android:layout_marginTop="50dip" 

La réponse de seydhe a un petit problème.

Le premier argument de la méthode getAtsortingbuteIntValue doit être l’espace de noms complet et pas seulement “Android”. Ainsi, l’extrait de code devrait être:

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

J’avais du mal à faire en sorte que cela fonctionne avec un tiroir coulissant horizontal jusqu’à ce que je réalise qu’il ne trouvait pas l’atsortingbut d’orientation et le traitait donc comme vertical.

il est préférable de lire le paramètre sans coder en dur la chaîne:

  int attrOrientation = android.R.attr.orientation; int attrTopOffset = android.R.attr.topOffset; int[] attrIds = new int [] {attrOrientation, attrTopOffset}; TypedArray a = context.obtainStyledAtsortingbutes(attrs, attrIds); int orientation = a.getInt(0, SlidingDrawer.ORIENTATION_VERTICAL); topOffset = a.getDimension(1, 0); a.recycle(); isVertical = (orientation == SlidingDrawer.ORIENTATION_VERTICAL); 

Un autre problème est dans le onMeasure.

J’ai utilisé le code suivant:

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

Malheureusement, vous ne pouvez pas définir la hauteur, mais plutôt le contraire. L’atsortingbut topOffset déterminera la taille du tiroir coulissant, mais sa taille, plutôt que sa taille.

Ça marche pour moi:

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

Mise en page XML:

 ...     ...    ...