Androidアプリ開発

Recyclerviewのアイテム選択エフェクト

この記事は約17分で読めます。
記事内に広告が含まれています。
スポンサーリンク

この記事はAndroidスマホ用のアプリ開発の中で、
今後の開発で再使用性が高いと思われるコーディングをまとめたものです。
Javaでの開発経験、XML構文規則、Androidのアプリ開発経験がある方を対象としています。
Androidのアプリ開発でお役にたててれば、嬉しいです。
(これから Androidのアプリ開発やJavaでの開発を始めたい方への案内は、
記事の最後で紹介します)

この記事のテーマ


Recyclerviewでアイテム選択時のエフェクトを実装する

UNITYのゲームエフェクトは参考になります

ポイント

ListViewではアイテム選択時に背景がグレー表示になり、選択しているアイテムを判別できます。
しかし、RecyclerViewではアイテム選択時のグレー表示がありません。
今回は、Recyclerviewでアイテム選択時のグレー表示(エフェクト)の実装方法を紹介します。

選択アイテムのグレー表示

RecyclerViewを継承したViewクラス

RecyclerViewを継承したVerticalListViewクラスを作成します。
アイテム選択時のエフェクトは内部クラスのAdapteronBindViewHolderに実装します。

public class VerticalListView extends RecyclerView{
    private OnItemClickListener onItemClickListener;
    public VerticalListView(Context context) {
        super(context);
        initialize(context);
    }
    public VerticalListView(Context context, AttributeSet set) {
        super(context, set);
        initialize(context);
    }
    public VerticalListView(Context context, AttributeSet set, int defaultAttr) {
        super(context, set, defaultAttr);
        initialize(context);
    }

    public interface OnItemClickListener {
        void onItemClick(View view, int position);
    }

    @SuppressWarnings("rawtypes")
    public void setOnItemClickListener(OnItemClickListener listener) {
        onItemClickListener = listener;
        Adapter adapter = getAdapter();
        if (adapter instanceof ArrayAdapter) {
            ArrayAdapter arrayAdapter = (ArrayAdapter)adapter;
            arrayAdapter.onItemClickListener = this.onItemClickListener;
        }
    }

    @SuppressWarnings("rawtypes")
    @Override
    public void setAdapter(Adapter adapter) {
        super.setAdapter(adapter);
        if (adapter instanceof ArrayAdapter) {
            ArrayAdapter arrayAdapter = (ArrayAdapter)adapter;
            arrayAdapter.onItemClickListener = this.onItemClickListener;
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        setOnItemClickListener(null);
        setAdapter(null);
        setLayoutManager(null);
    }

    private static class SimpleViewHolder extends ViewHolder {
        private SimpleViewHolder(View view){
            super(view);
        }
    }

    public static abstract class ArrayAdapter<E>
            extends Adapter<ViewHolder> {
        private List<E>             dataList;
        private OnItemClickListener onItemClickListener;
        private List<View>          viewList;
        private int                 id = 0;
        private Drawable            background = null;
        public ArrayAdapter(List<E> list) {
            dataList = new ArrayList<>(list.size());
            viewList = new ArrayList<>(list.size());
            dataList.addAll(list);
        }
        public ArrayAdapter(List<E> list, int id, Drawable background) {
            dataList = new ArrayList<>(list.size());
            viewList = new ArrayList<>(list.size());
            dataList.addAll(list);
            this.id = id;
            this.background = background;
        }
        public abstract View getView(ViewGroup parent);
        public abstract void onBindView(View view, E data, int position);

        @NonNull
        @Override
        public final ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new SimpleViewHolder(getView(parent));
        }

        @SuppressLint("ClickableViewAccessibility")
        @Override
        public final void onBindViewHolder(final ViewHolder holder, int position) {
            final View view = holder.itemView;
            E data = getItem(position);
            onBindView(view, data, position);
            viewList.add(holder.itemView);
            Drawable drawable = id != 0 ? holder.itemView.findViewById(id).getBackground() : null;
            holder.itemView.setOnTouchListener((View view1, MotionEvent motionEvent) -> {
                if (motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {
                    if (drawable != null) view1.findViewById(id).setBackground(drawable);
                } else {
                    if (background != null) view1.findViewById(id).setBackground(background);
                }
                return false;
            });
            holder.itemView.setOnClickListener(v -> {
                if (onItemClickListener != null) {
                    onItemClickListener.onItemClick(view, holder.getBindingAdapterPosition());
                }
            });
        }

        @Override
        public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
            super.onDetachedFromRecyclerView(recyclerView);
            for (View view : viewList) view.setOnClickListener(null);
            viewList = null;
            onItemClickListener = null;
            dataList = null;
        }

        @Override
        public final int getItemCount() {
            return (dataList == null ? 0 : dataList.size());
        }

        public E getItem(int position) {
            return dataList.get(position);
        }
    }

    public void initialize(Context context) {
        LinearLayoutManager manager = new LinearLayoutManager(context);
        manager.setOrientation(LinearLayoutManager.VERTICAL);
        setLayoutManager(manager);
    }
}

AdapterクラスのコンストラクタでViewHolderの背景に割り当てたDrawableのリソースIDとアイテム選択時のDrawableを設定します。
アイテム選択はViewHolderTouchListenerで判定します。

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <FrameLayout
        android:id="@+id/panel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        :
        android:background="@android:color/transparent">
        <TextView
            android:id="@+id/text_item"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            :
            />
    </FrameLayout>
</LinearLayout>

ViewHolderの背景に割り当てたDrawableのリソースIDは、panelです。
非選択の背景表示として、backgroundに透過を設定します。

RecyclerViewを継承したViewクラスの使用

RecyclerViewを継承したViewクラス内でアイテム選択時のエフェクトを行います。
RecyclerViewと同じ実装でAdapterをインスタンス化する際にViewHolderの背景に割り当てたDrawableのリソースIDとアイテム選択時のDrawableを追加で指定します。

    private VerticalListView.Adapter    taskAdapter;
    private VerticalListView            taskView;   
    :
    public void updateTaskList(List<Task> taskList) {
        taskAdapter = new VerticalListView.ArrayAdapter(taskList, R.id.panel, getDrawable(R.drawable.bg_grad_grey4)) {
            @Override
            public View getView(ViewGroup parent) {
                return LayoutInflater.from(parent.getContext()).inflate(R.layout.item_vertical1, parent, false);
            }
            @Override
            public void onBindView(View view, Object data, int position) {
                // アイテム内容表示
                :
            }
        };
        taskView.initialize(context);
        taskView.setAdapter(taskAdapter);
        taskView.setOnItemClickListener((view, position) -> {
            // アイテム選択時の処理
            :  
        });
        :

bg_grad_grey4はアイテム選択時の背景をグレー表示したDrawableです。

今回は、ここまでです。

Recyclerviewでアイテム選択時のエフェクトを実装しているAndroidアプリです。

誤字脱字、意味不明でわかりづらい、
もっと詳しく知りたいなどのご意見は、
このページの最後にある
コメントか、
こちらから、お願いいたします♪

ポチッとして頂けると、
次のコンテンツを作成する励みになります♪

ブログランキング・にほんブログ村へ

これからAndroidのアプリ開発やJavaでの開発を始めたい方へ

アプリケーション開発経験がない方や、アプリケーション開発経験がある方でも、JavaやC#などのオブジェクト指向言語が初めての方は、Androidのアプリ開発ができるようになるには、かなりの時間がかかります。
オンラインスクールでの習得を、強くおススメします。

未経験者からプログラマーを目指すのに最適です。まずは無料カウンセリングから♪

カリキュラムとサポートがしっかりしています。お得なキャンペーンとかいろいろやっています♪

ゲーム系に強いスクール、UnityやUnrealEngineを習得するのに最適です。まずは無料オンライン相談から♪

参考になったら、💛をポッチとしてね♪

スポンサーリンク
シェアする
msakiをフォローする
スポンサーリンク

コメント欄

タイトルとURLをコピーしました