web-dev-qa-db-fra.com

Définir un écouteur de clic sur un RecyclerView

J'utilise l'adaptateur RecycleView pour afficher des données dans une activité. Je souhaite implémenter onClickListener dans l'activité. Je règle actuellement onClickListener dans l'adaptateur comme d'habitude, ce qui fonctionne bien.

public void onBindViewHolder(MyHolder holder, final int position) {
    final Listdata data = listdata.get(position);
    holder.vname.setText(data.getName());

    holder.vname.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Toast.makeText(activity, "clicked on " +position, Toast.LENGTH_SHORT).show();
        }
    });
}

Cependant, je souhaite l'implémenter dans l'activité afin d'avoir un meilleur contrôle. Cela ne sert pas mon but. Je pense que ça va être utile pour beaucoup d'entre nous. 

6
Amir De

Vous devez vérifier ce didacticiel ici pour mieux comprendre comment vous pouvez obtenir le comportement que vous souhaitez. 

Si vous manipulez la onClickListener de votre activité, vous devez utiliser une implémentation de rappel avec une interface. Passez l'interface de l'activité à votre adaptateur, puis appelez la fonction de rappel de votre adaptateur lorsque vous cliquez sur certains éléments. 

Voici un exemple d'implémentation du tutoriel. 

Laissez-nous d'abord avoir l'interface. 

public interface OnItemClickListener {
    void onItemClick(ContentItem item);
}

Vous devez modifier votre adaptateur pour prendre l'auditeur comme paramètre comme celui indiqué ci-dessous. 

private final List<ContentItem> items;
private final OnItemClickListener listener;

public ContentAdapter(List<ContentItem> items, OnItemClickListener listener) {
    this.items = items;
    this.listener = listener;
}

Maintenant, dans votre méthode onBindViewHolder, définissez l'écouteur de clics. 

@Override public void onBindViewHolder(ViewHolder holder, int position) {
    holder.bind(items.get(position), listener);
}

public void bind(final ContentItem item, final OnItemClickListener listener) {
    ...
    itemView.setOnClickListener(new View.OnClickListener() {
        @Override public void onClick(View v) {
            listener.onItemClick(item);
        }
    });
}

Définissez maintenant l'adaptateur dans votre RecyclerView

recycler.setAdapter(new ContentAdapter(items, new ContentAdapter.OnItemClickListener() {
    @Override public void onItemClick(ContentItem item) {
        Toast.makeText(getContext(), "Item Clicked", Toast.LENGTH_LONG).show();
    }
}));

Donc tout le code de l'adaptateur ressemble à ce qui suit. 

public class ContentAdapter extends RecyclerView.Adapter<ContentAdapter.ViewHolder> {

    public interface OnItemClickListener {
        void onItemClick(ContentItem item);
    }

    private final List<ContentItem> items;
    private final OnItemClickListener listener;

    public ContentAdapter(List<ContentItem> items, OnItemClickListener listener) {
        this.items = items;
        this.listener = listener;
    }

    @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_item, parent, false);
        return new ViewHolder(v);
    }

    @Override public void onBindViewHolder(ViewHolder holder, int position) {
        holder.bind(items.get(position), listener);
    }

    @Override public int getItemCount() {
        return items.size();
    }

    static class ViewHolder extends RecyclerView.ViewHolder {

        private TextView name;
        private ImageView image;

        public ViewHolder(View itemView) {
            super(itemView);
            name = (TextView) itemView.findViewById(R.id.name);
            image = (ImageView) itemView.findViewById(R.id.image);
        }

        public void bind(final ContentItem item, final OnItemClickListener listener) {
            name.setText(item.name);
            Picasso.with(itemView.getContext()).load(item.imageUrl).into(image);
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override public void onClick(View v) {
                    listener.onItemClick(item);
                }
            });
        }
    }
}
6
Reaz Murshed

Si j'ai bien compris, vous voulez définir la logique de clic sur dans l'activité.

Vous pouvez le faire en définissant OnClickListener dans l'activité et en le transmettant au constructeur de l'adaptateur.

MyAdapter myAdapter = new MyAdapter(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Toast.makeText(activity, "clicked on " +position, Toast.LENGTH_SHORT).show();
        }
    }));

Et votre constructeur MyAdapter serait:

final private OnClickListener onClickListener;

public MyAdapter(OnClickListener onClickListener) {
    this.OnClickListener = OnClickListener;
}

Donc, votre nouveau code serait quelque chose comme ça

public void onBindViewHolder(MyHolder holder, final int position) {
    final Listdata data = listdata.get(position);
    holder.vname.setText(data.getName());

    holder.vname.setOnClickListener(onClickListener);

}

0
Sila Siebert

Créer une interface pour la classe d'adaptateur

private OnItemClickListener mListener;

public CustomAdapter(List<Listdata> listdata, OnItemClickListener listener) {
    mListener = listener;
    ...
    ...
}

private class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    ViewHolder(View view) {
        ...
        ...
        view.setOnClickLister(this);
    }

    @override
    public void onClick(View v) {
        mListener.onAdapterItemClick(getAdapterPosition())
    }
}

interface OnItemClickListener {
    void onAdapterItemClick(int position);
}

Laisser l'activité implémenter l'interface

public class CustomListActivity extends AppCompatActivity implements OnItemClickListener {

...
...

@override
public void onAdapterItemClick(int position) {
    Toast.makeText(activity, "clicked on " +position, Toast.LENGTH_SHORT).show();
}

Il y a une autre façon de faire, consultez this implementation

0
android_hub

Vous pouvez laisser votre Activity implémenter View.OnClickListener et le transmettre à l'adaptateur. Ci-dessous un exemple.

class  RAdapter extends RecyclerView.Adapter<>{
    View.OnClickListener listner;
    public RAdapter(View.OnClickListener listner) {
        this.listner = listner;
    }
    public void onBindViewHolder(MyHolder holder, final int position) {
        holder.vname.setOnClickListener(listner);

    }
}

Mais pour gérer le clic dans Activity, vous aurez besoin d’une position cliquée. Vous pouvez l'avoir avec adapter.getAdapterPosition() pour valider quel élément est cliqué.

En dehors de cela, si vous avez déjà une référence de Activity, vous pouvez avoir OnClick à l'intérieur de l'adaptateur et appeler une méthode publique de Activity avec position pour effectuer une action.

Une meilleure façon de gérer les clics dans ViewHolder. Voir l'exemple ci-dessous.

class Holder extends RecyclerView.ViewHolder implements View.OnClickListener {
        Button button;
        public Holder(View itemView) {
            super(itemView);
            button=itemView.findViewById(R.id.b1);
            button.setOnClickListener(this);
        }
        @Override
        public void onClick(View v) {
            if(v.getId()==R.id.b1){
                int position=getAdapterPosition();
                // Call a public method of Activity here 
                // with postion
            }
        }
    }
0
ADM

J'ai trouvé la méthode facile super duper! Je recommande celui-ci

Exemple de code:

public class ContentAdapter extends RecyclerView.Adapter<ContentAdapter.ViewHolder> {

public interface OnItemClickListener {
    void onItemClick(ContentItem item);
}

private final List<ContentItem> items;
private final OnItemClickListener listener;

public ContentAdapter(List<ContentItem> items, OnItemClickListener listener) {
    this.items = items;
    this.listener = listener;
}

@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_item, parent, false);
    return new ViewHolder(v);
}

@Override public void onBindViewHolder(ViewHolder holder, int position) {
    holder.bind(items.get(position), listener);
}

@Override public int getItemCount() {
    return items.size();
}

static class ViewHolder extends RecyclerView.ViewHolder {

    private TextView name;
    private ImageView image;

    public ViewHolder(View itemView) {
        super(itemView);
        name = (TextView) itemView.findViewById(R.id.name);
        image = (ImageView) itemView.findViewById(R.id.image);
    }

    public void bind(final ContentItem item, final OnItemClickListener listener) {
        name.setText(item.name);
        Picasso.with(itemView.getContext()).load(item.imageUrl).into(image);
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override public void onClick(View v) {
                listener.onItemClick(item);
            }
        });
    }
}
}

Et utilisez l’adaptateur RecyclerView en utilisant le code ci-dessous:

recycler.setAdapter(new ContentAdapter(items, new ContentAdapter.OnItemClickListener() {
@Override public void onItemClick(ContentItem item) {
    Toast.makeText(getContext(), "Item Clicked", Toast.LENGTH_LONG).show();
}
}));

j'ai trouvé cela de ici

J'espère que cela vous a aidé.

0
Amir De