web-dev-qa-db-ja.com

ExpandableListViewのスライドダウン効果

ExpandableListViewのアイテムを展開/折りたたみするときに、ニーススライドアップ/ダウン効果を使用できますか?

はいの場合、どのように?

前もって感謝します。

31
thomaus

したがって、これは this の完全な複製です。つまり、通常のリストを使用し、独自のドロップダウンビューを作成し、カスタムドロップダウンアニメーションを使用して成功しました(詳細についてはリンクを参照してください)。

編集:ステップバイステップガイド:

まず、xml list_rowを作成します。

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

ドロップダウンのアニメーションは次のとおりです。

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

次に、アダプター内で(もちろん、さらに構文を追加します。リスト内で見えなくなったときにドロップダウンを閉じないようにするには、何らかのパラメーターを使用して、これをホルダーに記憶する必要があります):

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

次に、ItemClickのリストで魔法が発生します。

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

最終コメント:これが最善の方法であるかどうかはわかりませんが、これが私にとってはうまくいったことです。

Edit:YouTubeでDevBytesが見ることができる別のソリューションがあります here

30
Warpzit

Warpzitが指摘したアンサーは正しいです。このアプローチを使用して、実際にどのように機能するかを知らなくても、アプリケーションに簡単に埋め込むことができるライブラリを提供しました。

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

詳細については、このブログ投稿をご覧ください: http://tjerktech.wordpress.com/2012/06/23/an-emerging-Android-ui-pattern-for-contextual-actions/

5
TjerkW

Warpzitによる実装は確かに機能しますが、ListViewの最適化された構造(つまり、子ビューの再利用/リサイクル)を使用しないため、多数の子供(100など)を持つグループをサポートする必要がある場合は使用できません。 )。代わりに、ExpandableListViewを拡張して、説明した手法 here を使用するAnimatedExpandableListViewを作成しました。そうすることで、AnimatedExpandableListViewは、最高のパフォーマンスを提供しながら、グループの拡大をアニメーション化できます。 ご覧ください

3
idunnololz

展開/折りたたみは、次のコードでは機能しません: https://github.com/tjerkw/Android-SlideExpandableListView なぜなら_OnItemExpandCollapseListener expandCollapseListener_ AbstractSlideExpandableListAdapterからはnullです。アニメーションの開始時にメソッドnotifiyExpandCollapseListenerが呼び出されますが、リスナーはnullになります。なぜなら、ActionSlideExpandableListViewを持っているからです:

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

アダプターを設定します:lv.setAdapter(slideAdapter);setAdapterからメソッドSlideExpandableListViewを呼び出し、SlideExpandableListAdapterの新しいインスタンスが作成されます。

私はこのように変更しました:setAdapterActionSlideExpandableListViewメソッドは、setAdapterからSlideExpandableListViewメソッドに渡される_AbstractSlideExpandableListAdapter.OnItemExpandCollapseListener_からもパラメーターとして受け取ります。そこでSlideExpandableListAdapterを作成すると、このリスナーも渡されます。

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

単純な解決策は、Gary Guoが作成したクラスAnimatedExpandableListViewを使用することです。これは、BaseExpandableListAdapterを拡張するExpandableListAdapterを既に使用している場合は、 here を使用できます。この方法では、ListViewの変更を使用する必要はありません。

AnimatedExpandableListAdapterの代わりにBaseExpandableListAdapterおよびAnimatedExpandableListViewの代わりにExpandableListViewをサブクラス化するだけで済みます。

@Override getChildrenCountの代わりに@Override getRealChildrenCountを使用してください。代わりに@Override getChildView,を使用して@Override getRealChildViewについても同じことを行います。

次に、アニメーションを次のように使用します。

    expandableListView.setOnGroupClickListener(new AnimatedExpandableListView.OnGroupClickListener() {
        @Override
        public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
            if (expandableListView.isGroupExpanded(groupPosition))
                expandableListView.collapseGroupWithAnimation(groupPosition);
            else
                expandableListView.expandGroupWithAnimation(groupPosition);
            return true;
        }

    });

もう1つの詳細は、レイアウトxmlファイルで、AnimatedExpandableListViewではなくExpandableListViewを参照する必要があることです。

<com.your.package.project.class.location.AnimatedExpandableListView
    Android:id="@+id/listView"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" />

プロジェクトのサンプルコードとAnimatedExpandableListViewクラスに関するコメントは、さらにサポートが必要な場合に非常に役立ちます。

0
Winston