Effet de glisser vers le bas sur ExpandableListView

est-il possible d'avoir un effet de glissement haut/bas lors de l'expansion/effondrement d'un élément D'une vue extensible?

Si oui, comment?

Merci d'avance.

29
demandé sur thomaus 2012-01-08 22:59:23

5 réponses

donc ceci est un duplicata complet de ce . En bref, j'ai utilisé une liste régulière, fait ma propre liste déroulante afficher, personnalisé déroulant animation et voila succès (voir le lien pour plus description).

Edit: guide étape par étape:

D'abord je crée le list_row xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/row_parent"
    android:orientation="vertical">
    <RelativeLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/row_simple_parent"
        >
    <View
        android:id="@+id/row_simple_parent_invis_cover"
        android:visibility="gone"
        android:layout_height="something that fills out your content"
        android:layout_width="match_parent"
        android:background="@android:color/transparent"/>
    </RelativeLayout>

    <!-- Dropdown -->
    <RelativeLayout 
        android:id="@+id/row_dropdown"
        android:layout_height="wrap_content"
        android:layout_width="match_parent">
    </RelativeLayout>
</LinearLayout>

l'animation pour dropdown est la suivante:

import android.app.Activity;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.animation.Animation;
import android.view.animation.Transformation;

/**
 * Class for handling collapse and expand animations.
 * @author Esben Gaarsmand
 *
 */
public class ExpandCollapseAnimation extends Animation {
    private View mAnimatedView;
    private int mEndHeight;
    private int mStartVisibility;

    /**
     * Initializes expand collapse animation. If the passed view is invisible/gone the animation will be a drop down, 
     * if it is visible the animation will be collapse from bottom
     * @param view The view to animate
     * @param duration
     */ 
    public ExpandCollapseAnimation(View view, int duration) {
        setDuration(duration);
        mAnimatedView = view;
        mEndHeight = mAnimatedView.getLayoutParams().height;
        mStartVisibility = mAnimatedView.getVisibility();
        if(mStartVisibility == View.GONE || mStartVisibility == View.INVISIBLE) {
            mAnimatedView.setVisibility(View.VISIBLE);
            mAnimatedView.getLayoutParams().height = 0;
        }
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        super.applyTransformation(interpolatedTime, t);
        if (interpolatedTime < 1.0f) {
            if(mStartVisibility == View.GONE || mStartVisibility == View.INVISIBLE) {
                mAnimatedView.getLayoutParams().height = (int) (mEndHeight * interpolatedTime);
            } else {
                mAnimatedView.getLayoutParams().height = mEndHeight - (int) (mEndHeight * interpolatedTime);
            }
            mAnimatedView.requestLayout();
        } else {
            if(mStartVisibility == View.GONE || mStartVisibility == View.INVISIBLE) {
                mAnimatedView.getLayoutParams().height = mEndHeight;
                mAnimatedView.requestLayout();
            } else {
                mAnimatedView.getLayoutParams().height = 0;
                mAnimatedView.setVisibility(View.GONE);
                mAnimatedView.requestLayout();
                mAnimatedView.getLayoutParams().height = mEndHeight;
            }
        }
    }

    /**
     * This methode can be used to calculate the height and set itm for views with wrap_content as height. 
     * This should be done before ExpandCollapseAnimation is created.
     * @param activity
     * @param view
     */
    public static void setHeightForWrapContent(Activity activity, View view) {
        DisplayMetrics metrics = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);

        int screenWidth = metrics.widthPixels;

        int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        int widthMeasureSpec = MeasureSpec.makeMeasureSpec(screenWidth, MeasureSpec.EXACTLY);

        view.measure(widthMeasureSpec, heightMeasureSpec);
        int height = view.getMeasuredHeight();
        view.getLayoutParams().height = height;
    }
}

puis dans mon adaptateur (vous bien sûr, ajouter plus de syntaxe, et si vous voulez que le dropdown ne se ferme pas lorsque hors de vue dans la liste, vous devez vous en souvenir dans le holder avec une sorte de paramètre aussi bien):

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder holder;
    if(convertView == null) {
        // setup holder
        holder = new ViewHolder();
        convertView = mInflater.inflate(R.layout.list_row, null);
        holder.mDropDown = convertView.findViewById(R.id.row_dropdown);
        convertView.setTag(holder);
    } else {
        // get existing row view
        holder = (ViewHolder) convertView.getTag();
    }
    holder.mDropDown.setVisibility(View.GONE);
    return convertView;
}

alors la magie se produit dans vos listes onItemClick:

@Override
public void onListItemClick(ListView list, View view, int position, long id) {
    final ListItem item = (ListItem) list.getAdapter().getItem(position);
    // set dropdown data
    ViewHolder holder = (ViewHolder) view.getTag();
    final View dropDown = holder.mDropDown;

    // set click close on top part of view, this is so you can click the view
    // and it can close or whatever, if you start to add buttons etc. you'll loose
    // the ability to click the view until you set the dropdown view to gone again.
    final View simpleView = view.findViewById(R.id.row_simple_parent_invis_cover);
    simpleView.setVisibility(View.VISIBLE);

    final Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if(msg.what == 0) {
                // first we measure height, we need to do this because we used wrap_content
                // if we use a fixed height we could just pass that in px.
                ExpandCollapseAnimation.setHeightForWrapContent(getActivity(), dropDown);
                ExpandCollapseAnimation expandAni = new ExpandCollapseAnimation(dropDown, DROP_DOWN_TIME);
                dropDown.startAnimation(expandAni);

                Message newMsg = new Message();

            } else if(msg.what == 1) {
                ExpandCollapseAnimation expandAni = new ExpandCollapseAnimation(dropDown, DROP_DOWN_TIME);
                dropDown.startAnimation(expandAni);

                simpleView.setOnClickListener(null);
                simpleView.setVisibility(View.GONE);
            }
        }
    };

    simpleView.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            handler.sendEmptyMessage(1);
        }
    });

    // start drop down animation
    handler.sendEmptyMessage(0);
}

commentaire Final: Je ne suis pas sûr que ce soit la meilleure façon de le faire, mais c'est ce qui a fonctionné pour moi.

Edit : il y a une solution différente par DevBytes sur youtube qui peut être consulté ici .

30
répondu Warpzit 2017-05-23 10:30:55

l'anwser souligné par Warpzit est correct. J'ai utilisé cette approche pour fournir une bibliothèque, vous pouvez facilement intégrer dans votre application sans avoir à savoir comment il fonctionne réellement:

https://github.com/tjerkw/Android-SlideExpandableListView

plus à ce sujet peuvent être lus dans ce billet de blog: http://tjerktech.wordpress.com/2012/06/23/an-emerging-android-ui-pattern-for-contextual-actions/

5
répondu TjerkW 2012-06-23 12:49:34

L'implémentation par Warpzit fonctionne certainement, mais elle est inutilisable si vous avez besoin de supporter des groupes avec beaucoup d'enfants (disons 100) car vous n'utiliserez pas la structure optimisée de ListView (i.e. la réutilisation et le recyclage des opinions des enfants). Au lieu de cela, J'ai fini par étendre ExpandableListView pour créer une Animated Expandablelistview qui utilise la technique que j'ai décrite ici . Ce faisant, la vue interactive animée D'Expandablepeut animer l'expansion du groupe. tout en offrant un rendement supérieur. Avoir un coup d'oeil.

3
répondu idunnololz 2017-05-23 12:26:38

l'expansion / effondrement ne fonctionne pas avec le code d'ici: https://github.com/tjerkw/Android-SlideExpandableListView parce que OnItemExpandCollapseListener expandCollapseListener de AbstractSlideExpandableListAdapter est null ; la méthode notifiyExpandCollapseListener est appelée lorsque l'animation commence, mais l'auditeur est null parce que: vous avez le ActionSlideExpandableListView :

ActionSlideExpandableListView lv = (ActionSlideExpandableListView) findViewById(R.id.list_view);
SlideExpandableListAdapter slideAdapter = new SlideExpandableListAdapter(adapter,R.id.expandable_toggle_button, R.id.expandable);

et vous réglez l'adaptateur: lv.setAdapter(slideAdapter); qui appelle la méthode setAdapter de SlideExpandableListView et là, une nouvelle instance de SlideExpandableListAdapter est créée.

j'ai changé comme ça: La méthode setAdapter de ActionSlideExpandableListView prend comme paramètre aussi AbstractSlideExpandableListAdapter.OnItemExpandCollapseListener qui est passé à la méthode setAdapter de SlideExpandableListView . Y quand je crée SlideExpandableListAdapter je passe aussi cet auditeur:

 public void setAdapter(ListAdapter adapter, AbstractSlideExpandableListAdapter.OnItemExpandCollapseListener expandCollapseListener) {
        this.adapter = new SlideExpandableListAdapter(adapter, expandCollapseListener);
        super.setAdapter(this.adapter);
    }

    public SlideExpandableListAdapter(ListAdapter wrapped, OnItemExpandCollapseListener expandCollapseListener) {
        this(wrapped, R.id.expandable_toggle_button, R.id.expandable);
        setItemExpandCollapseListener(expandCollapseListener);
    }
1
répondu Paul 2014-09-03 14:55:55

Essayer dans la classe java

       expListView.setAdapter(listAdapter);
    expListView.setOnGroupExpandListener(new OnGroupExpandListener() {
        int previousGroup = -1;

        @Override
        public void onGroupExpand(int groupPosition) {
            if(groupPosition != previousGroup)
                expListView.collapseGroup(previousGroup);
            previousGroup = groupPosition;
        }
    });
-2
répondu user3145931 2014-01-18 05:33:23