質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.57%

AndroidのRecyclerViewでクリック検知し、Intentを発行したい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 2,202

KumaChan

score 36

RecyclerViewをクリック検知してIntentを発行したいのですが、うまくいきません。

RecyclerViewのクリック検知ですが、自分が調べた範囲では「setOnClickListenerはRecyclerAdapterのonCreateViewHolderに書く」とありました。手元のリファレンス本もその記述だったので正攻法かと思いますが、そうするとRecyclerAdapterをActivityから切り離している場合、Intentの発行ができません。setOnClickListenerをActivity側に書けばよいのかもしれませんが…

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.RecyclerViewHolder> {

    // コンストラクタ
    public RecyclerAdapter(ArrayList<ListItem> data){
        items = data;
    }

    @NonNull
    @Override
    public RecyclerViewHolder onCreateViewHolder(@NonNull final ViewGroup viewGroup, int i) {
        // レイアウトインフレータ
        LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
        // ビューをインフレート
        View view = inflater.inflate(R.layout.row, viewGroup, false);
        // ビューホルダを生成
        RecyclerViewHolder holder = new RecyclerViewHolder(view);
        // ビューのクリック検知
        view.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View view) {
                                        // インテントを発行したい

                                    }
                                }

        );
        return holder;
    }


RecyclerAdapterのonCreateViewHolderにsetOnClickListenerを置き、onClickでIntentを発行する方法について教えていただけないでしょうか。(上記コードでクリック位置を取得し、ログ表示するところまではうまくいっています。)

それはやはり不可能で、setOnClickListenerをActivity側に記述した方がよいという場合、クリック位置(position)を取得する方法についても教えていただけるとうれしいです。

追記
いただいた回答をもとにいろいろ試したところ、ふつうにIntentを渡せました。
putExtraも使えます。コンテキストを取得できればなんとでもなるんですね!

    public RecyclerViewHolder onCreateViewHolder(@NonNull final ViewGroup viewGroup, int i) {
   ~中略~
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Context context = view.getContext();
                Intent intent = new Intent(context, ActivityPhotosDetail.class);
                intent.putExtra("name", "あああ");
                context.startActivity(intent);
            }
        });
  }
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

単にstartActivityとかを呼びたいだけなら、ViewがContextを保持しているのでそれ経由で呼び出し可能です。

view.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = Intent(...);
        view.getContext().startActivity(intent);
    }
});

余談ですが、一つ気になったのは、「setOnClickListenerはRecyclerAdapterのonCreateViewHolderに書く」という情報についてです。

RecyclerViewのViewHolderは1度生成されたあと、リストのスクロールなどにより何度も使い回されます。onCreateViewHolderはViewHolderの生成時にしか呼び出されませんから、クリックされたアイテムの位置によって処理を変える必要のある実装はonBindViewHolderの方ですべきです。
参考にされた情報がどういう状況を前提にしたものなのかわかりませんが、ご注意ください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/27 22:08

    ご提示いただいた方法でうまくいきました。
    シンプルでわかりやすいご回答、ありがとうございます。

    >余談ですが、一つ気になったのは、「setOnClickListenerはRecyclerAdapterのonCreateViewHolderに書く」という情報についてです。

    手元のリファレンス本がこの記述になっており、ウェブ上の情報ではonCreateViewHolderとonBindViewHolderの両方がありました。あまり意味も分からず前者を使っていましたが、ご指摘の通り、不具合の原因になりそうですね…今後は後者を使うようにしたいと思います。

    ご回答ならびに親身なアドバイス、本当にありがとうございます。
    また機会がありましたら、よろしくお願いいたします。

    キャンセル

+1

indexがほしいなら、

  • Adapterにinterfaceを実装する
  • 呼び出すActivity側でinterfaceの処理を実装する
  • Adapterに実装したinterfaceを渡す(コンストラクタで渡すなり、set作るなりはご自由に・・・)
  • AdapterのonBindViewHolderでindexを渡す
    でできます。

Adapter側の一部です。

public interface OnClickItemListener {
    void onClickItem (int index);
}

private OnClickItemListener listener;

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    final int index = holder.getAdapterPosition();

    holder.getView().setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (listener != null) {
                listener.onClickItem(index);
            }
        });
    });
}

public void setOnClickItemListener (OnClickItemListener listener) {
    this.listener = listener;
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/27 21:24

    早々のご回答ありがとうございます。
    やはりActivity継承のないAdapterでIntentの発行は無理なんですね…
    ちょっと残念ですが、教えていただいた方法で試してみたいと思います。

    それにしてもinterfaceで受け渡しとは…とても勉強になります。
    また機会がありましたら、よろしくお願いいたします。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.57%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る