LoginSignup
58
57

More than 5 years have passed since last update.

RecyclerViewのアイテムクリック

Last updated at Posted at 2015-01-09

ViewHolderにClickListener実装させろ (http://stackoverflow.com/a/24933117) というのを見たけど
1要素のクリックなら1つのOnClickListenerで処理できるんじゃないの?というアプローチ。

RecyclerViewとRecyclerView.Adapterの結合

RecyclerView.Adapterには、以下のコールバックメソッドがあります。

onAttachedToRecyclerView(RecyclerView)
onDetachedFromRecyclerView(RecyclerView)

これらのコールバックによって、AdapterはどのRecyclerViewにattachされたのかがわかります。

RecyclerViewからpositionを取得する

RecyclerViewには、getChildAdapterPosition(view)というメソッドがあります。
このメソッドにViewを渡すと、そのViewのAdapter上のpositionが取得できます。

実装

View.OnClickListenerを1つ実装し、onCreateViewHolder()で、クリック可能にするすべてのアイテムViewにセットします。
処理的には、独自のリスナーを定義して、それにコールバックする処理を書けばいいです。

View.OnClickListenerのonClick()はクリックされたViewをくれるので、getChildAdapterPosition()と組み合わせることで要素の位置がわかります。

CustomRecyclerAdapter
public class CustomRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements View.OnClickListener {

    private final List<Item> mList = new ArrayList<>();

    private RecyclerView mRecycler;

    private OnItemClickListener mListener;

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        mRecycler= recyclerView;
    }

    @Override
    public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
        super.onDetachedFromRecyclerView(recyclerView);
        mRecycler = null;
    }

    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        View view = mInflater.inflate();
        view.setOnClickListener(this);

        RecyclerView.ViewHolder holder = new RecyclerView.ViewHolder(view);

        return holder;
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        mListener = listener;
    }

    @Override
    public void onClick(View view) {
        if (mRecycler == null) {
            return;
        }

        if (mListener != null) {
            int position = mRecycler.getChildAdapterPosition(view);
            Item item = mList.get(position);   
            mListener.onItemClick(this, position, item);
        }
    }

    public static interface OnItemClickListener {
        public void onItemClick(CustomRecyclerAdapter adapter, int position, Item item);
    }

}

ちなみに、この実装では要素中の部分的なViewのクリックには対応できないです。
その場合は、素直にViewHolderにListenerを実装させましょう。

僕は、ViewHolderにAdapterを持たせて、ViewHolderからAdapterに一度コールバックしています。

CustomRecyclerAdapter
public class CustomRecyclerAdapter extends RecyclerView.Adapter<Holder> {

    // …

    private void onButtonClick(int position) {
        // アイテムのボタンクリック
    }

    static class Holder extends RecyclerView.ViewHolder implements OnClickListener {

        private CustomRecyclerAdapter mAdapter;

        public Holder(View itemView, CustomRecyclerAdapter adapter) {
            super(itemView);
            mAdapter = adapter;
            itemView.findViewById(R.id.button).setOnClickListener(this);
        }

        public void onClick(View view) {
            mAdapter.onButtonClick(getAdapterPosition());
        }
    }

実際はHolderにOnClickListener実装させるのではなく、ButterKnifeでbindしたほうがいいです。

58
57
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
58
57