Hat jemand, der RecyclerView
verwendet, einen Weg gefunden, um einen onClickListener
für Elemente im RecyclerView
festzulegen? Ich dachte daran, für jedes Element einen Listener für jedes Layout festzulegen, aber das scheint etwas zu umständlich zu sein. Ich bin sicher, dass es eine Möglichkeit gibt, dass der RecyclerView
auf das onClick
-Ereignis hört, aber ich kann es nicht ganz herausfinden.
Antworten
Zu viele Anzeigen?Normalerweise haben Sie mehr als ein Element in Ihrem CardView
, so dass Sie eine Layout-Ansicht benötigen, um sie zu umschließen und zu organisieren.
Sie können einem OnClickListener
diese Layout-Ansicht hinzufügen.
1. Fügen Sie eine ID zu Ihrem Layout hinzu. In diesem Fall ein LinearLayout
...
$
2. Holen Sie sich die Layout-Ansicht in Ihrer inneren ViewHolder
-Klasse.
public static class ViewHolder extends RecyclerView.ViewHolder{
private TextView nameView;
...
private LinearLayout linearLayout;
public ViewHolder(View itemView) {
super(itemView);
nameView = (TextView)itemView.findViewById(R.id.card_view_name);
...
linearLayout = (LinearLayout)itemView.findViewById(R.id.card_view_linearLayout);
}
}
$
3. Fügen Sie in onBindViewHolder
den Listener zu Ihrem Layout hinzu und verwenden Sie einen Rückruf, um Daten an die Activity
oder das Fragment
zu senden (nicht getestet).
@Override
public void onBindViewHolder(TrackAdapter.ViewHolder holder, final int position) {
String str = mStringList.get(position);
holder.nameView.setText(str);
...
holder.linearLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
callback.itemCallback(mStringList.get(position));
}
});
}
wie man Rückrufe verwendet, ist eine andere Geschichte
Sehr einfach, fügen Sie diese Klasse hinzu:
public class OnItemClickListener implements View.OnClickListener {
private int position;
private OnItemClickCallback onItemClickCallback;
public OnItemClickListener(int position, OnItemClickCallback onItemClickCallback) {
this.position = position;
this.onItemClickCallback = onItemClickCallback;
}
@Override
public void onClick(View view) {
onItemClickCallback.onItemClicked(view, position);
}
public interface OnItemClickCallback {
void onItemClicked(View view, int position);
}
}
Holen Sie sich eine Instanz des 'OnItemClickCallback' Interface und fügen Sie es in Ihre Activity oder Ihre Fragment:
private OnItemClickListener.OnItemClickCallback onItemClickCallback = new OnItemClickListener.OnItemClickCallback() {
@Override
public void onItemClicked(View view, int position) {
}
};
Übergeben Sie dann dieses Callback an Ihr RecyclerView:
recyclerView.setAdapter(new SimpleStringRecyclerViewAdapter(Arrays.asList("1", "2", "3"), onItemClickCallback));
Schließlich wäre dies Ihr Adapter:
public class SimpleStringRecyclerViewAdapter extends RecyclerView.Adapter {
private List mValues;
private OnItemClickListener.OnItemClickCallback onItemClickCallback;
public SimpleStringRecyclerViewAdapter(List items, OnItemClickListener.OnItemClickCallback onItemClickCallback) {
mValues = items;
this.onItemClickCallback = onItemClickCallback;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public final TextView mTextView;
public ViewHolder(View view) {
super(view);
mTextView = (TextView) view.findViewById(R.id.txt_title);
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.mTextView.setText(mValues.get(position));
holder.mTextView.setOnClickListener(new OnItemClickListener(position, onItemClickCallback));
}
@Override
public int getItemCount() {
return mValues.size();
}
}
Hier ist eine Strategie, die ein Ergebnis ähnlich der Implementierung von ListView
liefert, in der Sie den Listener auf der Ebene der Activity
oder Fragment
statt auf der Ebene des Adapter
oder ViewHolder
definieren können. Es definiert auch einige abstrakte Klassen, die sich um einen Großteil der Standardarbeiten von Adaptern und Holdern kümmern.
Abstrakte Klassen
Definieren Sie zuerst einen abstrakten Holder
, der RecyclerView.ViewHolder
erweitert und einen generischen Datentyp, T
, definiert, der zum Binden von Daten an die Ansichten verwendet wird. Die Methode bindViews
wird von einer Unterklasse implementiert, um Daten mit den Ansichten zu verknüpfen.
public abstract class Holder extends RecyclerView.ViewHolder {
T data;
public Holder(View itemView) {
super(itemView);
}
public void bindData(T data){
this.data = data;
bindViews(data);
}
abstract protected void bindViews(T data);
}
Erstellen Sie außerdem einen abstrakten Adapter
, der RecyclerView.Adapter>
erweitert. Dies definiert 2 der 3 Schnittstellenmethoden, und eine Unterklasse muss die letzte Methode, onViewHolderCreated
, implementieren.
public abstract class Adapter extends RecyclerView.Adapter> {
List list = new ArrayList<>();
@Override
public void onBindViewHolder(Holder holder, int position) {
holder.bindData(list.get(position));
}
@Override
public int getItemCount() {
return list.size();
}
public T getItem(int adapterPosition){
return list.get(adapterPosition);
}
}
Konkrete Klassen
Erstellen Sie nun eine neue konkrete Klasse, die Holder
erweitert. Diese Methode muss nur die Ansichten definieren und das Binden verarbeiten. Hier verwende ich die ButterKnife-Bibliothek, aber Sie können auch die Methoden itemView.findViewById(...)
verwenden.
public class PersonHolder extends Holder{
@Bind(R.id.firstname) TextView firstname;
@Bind(R.id.lastname) TextView lastname;
public PersonHolder(View view){
super(view);
ButterKnife.bind(this, view);
}
@Override
protected void bindViews(Person person) {
firstname.setText(person.firstname);
lastname.setText(person.lastname);
}
}
Zuletzt haben Sie in Ihrer Activity
oder Fragment
-Klasse, die das RecyclerView
hält, diesen Code:
// Adapter erstellen, dies geschieht in der übergeordneten Activity oder Fragment des RecyclerView
adapter = new Adapter(){
@Override
public PersonHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout_person_view, parent, false);
PersonHolder holder = new PersonHolder(v);
v.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
int itemPos = holder.getAdapterPosition();
Person person = getItem(itemPos);
// etwas mit der Person tun
EventBus.getDefault().postSticky(new PersonClickedEvent(itemPos, person));
}
});
return holder;
}
};
Dies funktioniert.
public class ServiceListAdapter extends RecyclerView.Adapter {
private final Context mContext;
private List categoryList;
private View.OnClickListener onClickListener;
public ServiceListAdapter(Context mContext, List categoryList, View.OnClickListener onClickListener) {
this.categoryList = categoryList;
this.mContext = mContext;
this.onClickListener = onClickListener;
}
@Override
public ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
final RowServiceListBinding binding = DataBindingUtil.inflate(inflater, R.layout.row_service_list, parent, false);
return new ViewHolder(binding.getRoot(), binding);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.binding.rlService.setOnClickListener(onClickListener);
holder.binding.rlService.setTag(position);
}
@Override
public int getItemCount() {
return categoryList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private final RowServiceListBinding binding;
public ViewHolder(final View view, final RowServiceListBinding binding) {
super(view);
this.binding = binding;
}
@UiThread
public void bind(final ServiceListModel mAddressModel) {
//this.binding.setAddress(mAddressModel);
}
}
}
Verwendung in Aktivität/Fragment
ServiceListAdapter adapter = new ServiceListAdapter(context, serviceList, new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.rlService:
int pos = (int) v.getTag();
serviceList.remove(position);
break;
}
}
});
- See previous answers
- Weitere Antworten anzeigen