1062 Stimmen

Wie man RecyclerView mit mehreren Ansichtstypen erstellt

Von Erstellen von dynamischen Listen mit RecyclerView:

Wenn wir einen RecyclerView.Adapter erstellen, müssen wir einen ViewHolder angeben, der sich mit dem Adapter verbindet.

public class MyAdapter extends RecyclerView.Adapter {

    private String[] mDataset;

    public MyAdapter(String[] myDataset) {
        mDataset = myDataset;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView mTextView;
        public ViewHolder(TextView v) {
            super(v);
            mTextView = v;
        }
    }

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

        //findViewById...

        ViewHolder vh = new ViewHolder(v);
        return vh;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.mTextView.setText(mDataset[position]);
    }

    @Override
    public int getItemCount() {
        return mDataset.length;
    }
}

Ist es möglich, einen RecyclerView mit mehreren Ansichtstypen zu erstellen?

2voto

Link182 Punkte 675

Die Implementierung von Ansichtstypen wird mit Kotlin einfacher. Hier ist ein Beispiel mit dieser leichten Bibliothek https://github.com/Link184/KidAdapter

recyclerView.setUp {
    withViewType {
        withLayoutResId(R.layout.item_int)
        withItems(mutableListOf(1, 2, 3, 4, 5, 6))
        bind { // this - ist der Adapter-View-Holder itemView, it - das aktuelle Element
            intName.text = it.toString()
        }
    }

    withViewType("SECOND_STRING_TAG") {
        withLayoutResId(R.layout.item_text)
        withItems(mutableListOf("acht", "neun", "zehn", "elf", "zwölf"))
        bind {
            stringName.text = it
        }
    }
}

2voto

Vitaly Punkte 549

Sie können die Bibliothek verwenden: https://github.com/vivchar/RendererRecyclerViewAdapter

mRecyclerViewAdapter = new RendererRecyclerViewAdapter(); /* Inkludiert von der Bibliothek */
mRecyclerViewAdapter.registerRenderer(new SomeViewRenderer(SomeModel.TYPE, this));
mRecyclerViewAdapter.registerRenderer(...); /* Sie können mehrere Arten von Zellen verwenden */

Für jedes Element sollten Sie ein ViewRenderer, ViewHolder und SomeModel implementieren:

ViewHolder - es handelt sich um einen einfachen Ansichtshalter des Recycler-Views.

SomeModel - es handelt sich um Ihr Modell mit der ItemModel-Schnittstelle

public class SomeViewRenderer extends ViewRenderer {

    public SomeViewRenderer(final int type, final Context context) {
        super(type, context);
    }

    @Override
    public void bindView(@NonNull final SomeModel model, @NonNull final SomeViewHolder holder) {
        holder.mTitle.setText(model.getTitle());
    }

    @NonNull
    @Override
    public SomeViewHolder createViewHolder(@Nullable final ViewGroup parent) {
        return new SomeViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.some_item, parent, false));
    }
}

Weitere Details finden Sie in der Dokumentation.

1voto

Pavlo Ostasha Punkte 15790

Wenn Sie es in Verbindung mit Android Data Binding verwenden möchten, schauen Sie sich das https://github.com/evant/binding-collection-adapter an - es ist bei weitem die beste Lösung für die Verwendung von mehreren Ansichtstypen im RecyclerView, die ich je gesehen habe.

Sie können es wie folgt verwenden

var items: AsyncDiffPagedObservableList =
        AsyncDiffPagedObservableList(GenericDiff)

    val onItemBind: OnItemBind =
        OnItemBind { itemBinding, _, item -> itemBinding.set(BR.item, item.layoutRes) }

Und dann im Layout, wo die Liste ist:

Ihre Listenelemente müssen das BaseListItem Interface implementieren, das so aussieht:

interface BaseListItem {
    val layoutRes: Int
}

Und die Listenelementansicht sollte ungefähr so aussehen:

   ...

Wo YourListItem das BaseListItem implementiert.

1voto

Genius8020 Punkte 135

Zuerst müssen Sie zwei Layout-XML-Dateien erstellen. Danach sind innerhalb des Recyclerview-Adapters TYPE_CALL und TYPE_EMAIL zwei statische Werte mit 1 bzw. 2 in der Adapterklasse.

Definieren Sie nun zwei statische Werte auf der Ebene der Recycler-View-Adapterklasse, z. B .: private static int TYPE_CALL = 1; private static int TYPE_EMAIL = 2;

Erstellen Sie nun den View-Holder mit mehreren Ansichten wie folgt:

class CallViewHolder extends RecyclerView.ViewHolder {

    private TextView txtName;
    private TextView txtAddress;

    CallViewHolder(@NonNull View itemView) {
        super(itemView);
        txtName = itemView.findViewById(R.id.txtName);
        txtAddress = itemView.findViewById(R.id.txtAddress);
    }
}

class EmailViewHolder extends RecyclerView.ViewHolder {

    private TextView txtName;
    private TextView txtAddress;

    EmailViewHolder(@NonNull View itemView) {
        super(itemView);
        txtName = itemView.findViewById(R.id.txtName);
        txtAddress = itemView.findViewById(R.id.txtAddress);
    }
}

Jetzt codieren Sie wie unten in der onCreateViewHolder- und onBindViewHolder-Methode im Recyclerview-Adapter:

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
    View view;
    if (viewType == TYPE_CALL) { // für das Anruflayout
        view = LayoutInflater.from(context).inflate(R.layout.item_call, viewGroup, false);
        return new CallViewHolder(view);

    } else { // für das E-Mail-Layout
        view = LayoutInflater.from(context).inflate(R.layout.item_email, viewGroup, false);
        return new EmailViewHolder(view);
    }
}

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
    if (getItemViewType(position) == TYPE_CALL) {
        ((CallViewHolder) viewHolder).setCallDetails(employees.get(position));
    } else {
        ((EmailViewHolder) viewHolder).setEmailDetails(employees.get(position));
    }
}

1voto

Ich habe etwas Ähnliches gemacht. Ich habe "fragmentType" übergeben und zwei ViewHolders erstellt und basierend darauf meine Layouts in einem einzelnen Adapter klassifiziert, der verschiedene Layouts und LayoutManagers haben kann.

private Context mContext;
protected IOnLoyaltyCardCategoriesItemClicked mListener;
private String fragmentType;
private View view;

public LoyaltyCardsCategoriesRecyclerViewAdapter(Context context, IOnLoyaltyCardCategoriesItemClicked itemListener, String fragmentType) {
    this.mContext = context;
    this.mListener = itemListener;
    this.fragmentType = fragmentType;
}

public class LoyaltyCardCategoriesFragmentViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    private ImageView lc_categories_iv;
    private TextView lc_categories_name_tv;
    private int pos;

    public LoyaltyCardCategoriesFragmentViewHolder(View v) {
        super(v);
        view.setOnClickListener(this);
        lc_categories_iv = (ImageView) v.findViewById(R.id.lc_categories_iv);
        lc_categories_name_tv = (TextView) v.findViewById(R.id.lc_categories_name_tv);
    }

    public void setData(int pos) {
        this.pos = pos;
        lc_categories_iv.setImageResource(R.mipmap.ic_launcher);
        lc_categories_name_tv.setText("Loyalty Card Categories");
    }

    @Override
    public void onClick(View view) {
        if (mListener != null) {
            mListener.onLoyaltyCardCategoriesItemClicked(pos);
        }
    }
}

public class MyLoyaltyCardsFragmentTagViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    public ImageButton lc_categories_btn;
    private int pos;

    public MyLoyaltyCardsFragmentTagViewHolder(View v) {
        super(v);
        lc_categories_btn = (ImageButton) v.findViewById(R.id.lc_categories_btn);
        lc_categories_btn.setOnClickListener(this);
    }

    public void setData(int pos) {
        this.pos = pos;
        lc_categories_btn.setImageResource(R.mipmap.ic_launcher);
    }

    @Override
    public void onClick(View view) {
        if (mListener != null) {
            mListener.onLoyaltyCardCategoriesItemClicked(pos);
        }
    }
}

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (fragmentType.equalsIgnoreCase(Constants.LoyaltyCardCategoriesFragmentTag)) {
        view = LayoutInflater.from(mContext).inflate(R.layout.loyalty_cards_categories_frag_item, parent, false);
        return new LoyaltyCardCategoriesFragmentViewHolder(view);
    } else if (fragmentType.equalsIgnoreCase(Constants.MyLoyaltyCardsFragmentTag)) {
        view = LayoutInflater.from(mContext).inflate(R.layout.my_loyalty_cards_categories_frag_item, parent, false);
        return new MyLoyaltyCardsFragmentTagViewHolder(view);
    } else {
        return null;
    }
}

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
    if (fragmentType.equalsIgnoreCase(Constants.LoyaltyCardCategoriesFragmentTag)) {
        ((LoyaltyCardCategoriesFragmentViewHolder) holder).setData(position);
    } else if (fragmentType.equalsIgnoreCase(Constants.MyLoyaltyCardsFragmentTag)) {
        ((MyLoyaltyCardsFragmentTagViewHolder) holder).setData(position);
    }
}

@Override
public int getItemCount() {
    return 7;
}

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