677 Stimmen

RecyclerView onClick

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.

0voto

RickPat Punkte 487

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

0voto

Hamzeh Soboh Punkte 7354

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();
    }
}

0voto

bcorso Punkte 43188

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;
    }
};

-1voto

Rupesh Rathore Punkte 339

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;
            }
        }
    });

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X