web-dev-qa-db-ja.com

アイテムのクリック時のRecyclerViewアニメーション

私は自分のrecyclerviewアニメーションを実装しようとしています-外部ライブラリを使用せずにこれを実現したいと思います。これは理論的なアニメーションがどのように見えるかです。

enter image description here

ユーザーがリストの項目をクリックすると、別のビューを開くアニメーションが発生します。

最小限のコード、おそらく疑似コードでの高レベルでは、そのようなアニメーションを作成するためのプロセスは何でしょうか?

ユーザーが同じアイテムまたは別のアイテムをクリックした場合にもアニメーションを逆に実行できることにも注意したい

私はRecyclerViewクラスにあまり詳しくないので、このクラスとそれに関連するアニメーションについて詳しく知りたいと思います。

23
AndyRoid

解決:

この問題を解決した方法は、View.OnClickListenerであるViewHolderクラスにリスナーextends RecyclerView.ViewHolderを実装することでした。したがって、次のコードを取得します。

public static class ExampleViewHolder extends RecyclerView.ViewHolder 
    implements View.OnClickListener {

    private int originalHeight = 0;
    private boolean isViewExpanded = false;
    private YourCustomView yourCustomView

    // ..... CODE ..... //

}

変数originalHeightおよびisViewExpandedは、アニメーションプロセスで使用されます。コンストラクタで、ビューをView.OnClickListenerに初期化します。

public ExampleViewHolder(View v) {
     super(v);
     v.setOnClickListener(this);

     // Initialize other views, like TextView, ImageView, etc. here

     // If isViewExpanded == false then set the visibility 
     // of whatever will be in the expanded to GONE

     if (isViewExpanded == false) {
         // Set Views to View.GONE and .setEnabled(false)
         yourCustomView.setVisibility(View.GONE);
         yourCustomView.setEnabled(false);
     }

 }

コンストラクタが処理されたので、ユーザーが個々のRecyclerViewアイテムをクリックしたときに何が起こるかを構成します。ここで役立つクラスは、ValueAnimatorオブジェクトとAnimationオブジェクトです。これを実現するために、onClickメソッドを次のようにオーバーライドします。

@Override
public void onClick(final View view) {
    // If the originalHeight is 0 then find the height of the View being used 
    // This would be the height of the cardview
    if (originalHeight == 0) {
            originalHeight = view.getHeight();
        }

    // Declare a ValueAnimator object
    ValueAnimator valueAnimator;
        if (!mIsViewExpanded) {
            yourCustomView.setVisibility(View.VISIBLE);
            yourCustomView.setEnabled(true);
            mIsViewExpanded = true;
            valueAnimator = ValueAnimator.ofInt(originalHeight, originalHeight + (int) (originalHeight * 2.0)); // These values in this method can be changed to expand however much you like
        } else {
            mIsViewExpanded = false;
            valueAnimator = ValueAnimator.ofInt(originalHeight + (int) (originalHeight * 2.0), originalHeight);

            Animation a = new AlphaAnimation(1.00f, 0.00f); // Fade out

            a.setDuration(200);
            // Set a listener to the animation and configure onAnimationEnd
            a.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {

                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    yourCustomView.setVisibility(View.INVISIBLE);
                    yourCustomView.setEnabled(false);
                }

                @Override
                public void onAnimationRepeat(Animation animation) {

                }
            });

            // Set the animation on the custom view
            yourCustomView.startAnimation(a);
        }
        valueAnimator.setDuration(200);
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator animation) {
                Integer value = (Integer) animation.getAnimatedValue();
                view.getLayoutParams().height = value.intValue();
                view.requestLayout();
            }
        });


        valueAnimator.start();

    }

ここで、RecyclerViewの個々のカードビューをタッチすると(CardViewの設定があると仮定すると、展開されるはずです。必ず、xmlファイルでcustomViewを適切に宣言してください(たとえば、 CardViewに触れると展開され、他のビューの下にcustomViewが適切に割り当てられます。宣言すると可視性がなくなり、上記のコードのようにアニメーションが開始されると、可視性がVisibleに設定されます。ビューを有効にします。

これが誰かを助けることを願っています。

15
AndyRoid

@AndyRoidの答えのより簡単な代替方法は、Android:animateLayoutChanges="true"プロパティを使用することです。この方法では、アニメーションコードを記述する必要はありません。ただし、アニメーションを制御する必要がある場合は、この方法にはなりません。

OnClickListenerを作成する必要があります:

class CardTapListener implements View.OnClickListener {
    @Override
    public void onClick(View v) {
        View someView = v.findViewById(R.id.view_to_expand);

        if (someView.getVisibility() == View.GONE) {
            someView.setVisibility(View.VISIBLE);
        }
        else if (someView.getVisibility() == View.VISIBLE){
            someView.setVisibility(View.GONE);
        }

    }
}

すべてのViewHolderに添付:

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
    View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.view_holder_layout, viewGroup, false);
    v.setOnClickListener(new CardTapListener());
    return new ItemViewHolder(v);
}

新しいアイテムをバインドするときは、ビューを折りたたむことを忘れないでください。

@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) {
    ...
    // Collapse (probably opened by user previously) view
    ItemViewHolder itemHolder = (ItemViewHolder) viewHolder;
    itemHolder.description.setVisibility(View.GONE);
    ...

}

view_holder_layout.xml:

<LinearLayout
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:animateLayoutChanges="true"
    Android:orientation="vertical">

 ...

    <AnyViewHere
        Android:visibility="gone"
        Android:id="@+id/view_to_expand" />

 </LinearLayout>
4
Max Malysh