56 votes

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

Je suis en train de mettre en œuvre un SlidingDrawer qui va occuper la pleine largeur de l'écran, mais dont la hauteur est déterminée dynamiquement par son contenu: en d'autres termes, la norme fill_parent présentation comportement de la largeur et de wrap_content de la hauteur. C'est exactement comment je l'ai spécifié dans le layout XML (voir ci-dessous), mais le glissement du tiroir s'ouvre toujours à la pleine hauteur de l'écran. La hauteur de mon contenu varie, mais généralement, c'est seulement la moitié de la hauteur de l'écran, donc je me retrouve avec un gros écart en dessous. Ce que j'aimerais c'est pour que le contenu s'asseoir correctement sur le bas de l'écran.

J'ai essayé tout ce que je peux penser à le réparer, mais rien n'a fonctionné jusqu'ici. Si j'ai mis l' SlidingDrawers' layout_height pour une valeur spécifique (par exemple, 160dip), il fonctionne, mais ce n'est pas ce dont j'ai besoin: elle doit être dynamique. Bien sûr, j'ai fait que tous les éléments enfants ont leur de hauteur définie à l' wrap_content trop.

La documentation sur le SlidingDrawer est un peu vague, et je n'ai pas été en mesure de trouver des exemples de ce que je suis après. Si quelqu'un peut voir où je vais mal, je vous remercie de votre aide!

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

127voto

seydhe Points 1176

L' onMeasure() méthode de la SlidingDrawer classe fondamentalement remplace les modes de disposition d' fill_parent, c'est pourquoi, layout_height="wrap_content" n'est pas de travail.

Pour contourner ce problème, vous pouvez étendre SlidingDrawer avec une re-mise en œuvre onMeasure() méthode qui honore l' layout_width et layout_height attributs. Vous pouvez ensuite utiliser cette classe personnalisée dans votre XML disposition par le remplacement, <SlidingDrawer ...> avec <fully.qualified.package.ClassName ...>.

A noter que depuis le tiroir ne sera plus le remplissage de la mère de mise en page, vous devrez l'inclure dans un LinearLayout avec la gravité de l'attribut défini sur le bord où le tiroir doit être.

Ci-dessous sont une classe que j'ai créé dans ce but et un exemple de mise en page.

WrappingSlidingDrawer classe :

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

Exemple de mise en page (en supposant que WrappingSlidingDrawer est dans le package 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>

5voto

A B Points 97

juste mis à pmargin dans un tiroir coulissant dans votre xml

 android:layout_marginTop="50dip"
 

5voto

museofwater Points 161

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

Le premier argument de getAttributeIntValue doit être l'espace de noms complet, pas seulement "android". Donc, l'extrait de code devrait être:

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

J'avais du mal à le faire fonctionner avec un tiroir coulissant horizontal jusqu'à ce que je réalise qu'il ne trouvait pas l'attribut orientation et le traitait donc comme vertical.

4voto

herschel Points 2706

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.obtainStyledAttributes(attrs, attrIds);
    int orientation = a.getInt(0, SlidingDrawer.ORIENTATION_VERTICAL);
    topOffset = a.getDimension(1, 0);
    a.recycle(); 

    isVertical = (orientation == SlidingDrawer.ORIENTATION_VERTICAL);
 

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

2voto

schwiz Points 13679

Malheureusement, vous ne pouvez pas régler la hauteur, mais plutôt le contraire. L'attribut topOffset déterminera la taille du tiroir coulissant, mais sa taille à raser plutôt que sa taille.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X