Farklı türde satır şişirme işlemlerini görüntüleme ve işleme


124

Yeni ile çalışmaya çalışıyorum RecyclerView, ancak RecyclerViewfarklı türdeki satırların / kart görünümlerinin şişirildiği bir örnek bulamadım .

İle ListViewI geçersiz getViewTypeCountve getItemViewTypesatırların farklı işleme için.

Bunu "eski" yol gibi mi yapmalıyım yoksa onunla bir şey LayoutManagermi yapmalıyım ? Biri beni doğru yöne yönlendirebilir mi diye merak ediyordum. Çünkü sadece tek tip örnekler bulabiliyorum.

Biraz farklı kartların bir listesine sahip olmak istiyorum. Yoksa sadece içinde bir scrollViewtane kullanmalı mıyım ... adaptörsüz yapmalı mıyım ?cardViewsrecyclerView


öğe türleriniz arasındaki fark nedir? geri dönüşümcü görünümü farklı türlere nasıl tepki vermelidir? Genel olarak, geri
dönüşümlü bir görünümle yapamayacağınız

Aslında google oyun mağazasında gördüğünüz gibi. En üstte bir başlığınız olabilir, ardından üç kart görebilirsiniz, ardından bilgi içeren bir bölümünüz olur. Bu bir geri dönüşüm görünümünde / liste görünümünde mi yapılır? Veya kaydırma görünümü? Çünkü bu bir kaydırma görünümüyse, önceden tüm düzenleri belirlemem gerekiyor. Bir liste görünümü ile veri setime belirli nesneleri ekleyebilirim ve doğru düzen şişirilir. Bu yüzden, yeni Recyclerview ile son bölümü nasıl yapacağımı bilmek istiyorum, listview gibi yöntemleri geçersiz kılmam gerekir mi?
Lokkio



Bu bağlantıyı kontrol edin, sizin için işe yarayacaktır: - stackoverflow.com/a/39972276/3946958
Ravindra Kushwaha

Yanıtlar:


202

Satır / bölüm mantığını iOS'un UITableView'ına benzer şekilde kullanmak, Android'de iOS'ta olduğu kadar basit değildir, ancak RecyclerView'u kullandığınızda - yapabileceklerinizin esnekliği çok daha fazladır.

Sonunda, her şey Adaptörde ne tür bir görünüm görüntülediğinizi nasıl anlayacağınızla ilgili. Bunu bir kez anladığınızda, kolay yelken açmanız gerekir (gerçekten değil, ama en azından bunu halledeceksiniz).

Bağdaştırıcı, geçersiz kılmanız gereken iki yöntemi ortaya çıkarır:

getItemViewType(int position)

Bu yöntemin varsayılan uygulaması her zaman 0 döndürür ve yalnızca 1 tür görünüm olduğunu gösterir. Sizin durumunuzda, öyle değil ve bu nedenle hangi satırın hangi görünüm türüne karşılık geldiğini belirlemenin bir yolunu bulmanız gerekecek. Bunu sizin için satırlar ve bölümlerle yöneten iOS'tan farklı olarak, burada güvenebileceğiniz yalnızca bir dizine sahip olacaksınız ve bir konumun bir bölüm başlığıyla ne zaman ve ne zaman ilişkili olduğunu bilmek için geliştirici becerilerinizi kullanmanız gerekecek. normal bir sıra.

createViewHolder(ViewGroup parent, int viewType)

Yine de bu yöntemi geçersiz kılmanız gerekir, ancak genellikle insanlar viewType parametresini yok sayarlar. Görünüm türüne göre, doğru düzen kaynağını şişirmeniz ve buna göre görünüm tutucunuzu oluşturmanız gerekir. RecyclerView, farklı görünüm türlerinin farklı görünüm türlerinin çakışmasını önleyecek şekilde geri dönüştürülmesini sağlayacaktır.

Varsayılan bir LayoutManager kullanmayı planlıyorsanız, örneğin LinearLayoutManager, gitmekte fayda var . Kendi LayoutManager uygulamanızı yapmayı planlıyorsanız, biraz daha fazla çalışmanız gerekir. Gerçekten çalışmanız gereken tek API, findViewByPosition(int position)belirli bir pozisyonda belirli bir görünümü veren şeydir. Bu görünümün türüne bağlı olarak muhtemelen onu farklı bir şekilde düzenlemek isteyeceğiniz için birkaç seçeneğiniz vardır:

  1. Genellikle ViewHolder modelini kullanırken, görünümün etiketini görünüm tutucu ile ayarlarsınız. Bunu, görünüm yöneticisine bunu ifade eden bir alan ekleyerek görünümün ne tür olduğunu bulmak için yerleşim yöneticisinde çalışma süresi sırasında kullanabilirsiniz.

  2. Hangi konumun hangi görünüm türüyle ilişkili olduğunu belirleyen bir işleve ihtiyacınız olacağından, bu yöntemi bir şekilde küresel olarak erişilebilir hale getirebilirsiniz (belki verileri yöneten bir tekli sınıf olabilir mi?) Ve sonra aynı yöntemi şuna göre sorgulayabilirsiniz: pozisyon.

İşte bir kod örneği:

// in this sample, I use an object array to simulate the data of the list. 
// I assume that if the object is a String, it means I should display a header with a basic title.
// If not, I assume it's a custom model object I created which I will use to bind my normal rows.
private Object[] myData;

public static final int ITEM_TYPE_NORMAL = 0;
public static final int ITEM_TYPE_HEADER = 1;

public class MyAdapter extends Adapter<ViewHolder> {

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        if (viewType == ITEM_TYPE_NORMAL) {
            View normalView = LayoutInflater.from(getContext()).inflate(R.layout.my_normal_row, null);
            return new MyNormalViewHolder(normalView); // view holder for normal items
        } else if (viewType == ITEM_TYPE_HEADER) {
            View headerRow = LayoutInflater.from(getContext()).inflate(R.layout.my_header_row, null);
            return new MyHeaderViewHolder(headerRow); // view holder for header items
        }
    }


    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {

        final int itemType = getItemViewType(position);

        if (itemType == ITEM_TYPE_NORMAL) {
            ((MyNormalViewHolder)holder).bindData((MyModel)myData[position]);
        } else if (itemType == ITEM_TYPE_HEADER) {
            ((MyHeaderViewHolder)holder).setHeaderText((String)myData[position]);
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (myData[position] instanceof String) {
            return ITEM_TYPE_HEADER;
        } else {
            return ITEM_TYPE_NORMAL;
        }
    }

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

İşte bu görüntü sahiplerinin nasıl görünmesi gerektiğine dair bir örnek:

public MyHeaderViewHolder extends ViewHolder {

    private TextView headerLabel;    

    public MyHeaderViewHolder(View view) {
        super(view);

        headerLabel = (TextView)view.findViewById(R.id.headerLabel);
    }

    public void setHeaderText(String text) {
        headerLabel.setText(text);
    }    
}


public MyNormalViewHolder extends ViewHolder {

    private TextView titleLabel;
    private TextView descriptionLabel;    

    public MyNormalViewHolder(View view) {
        super(view);

        titleLabel = (TextView)view.findViewById(R.id.titleLabel);
        descriptionLabel = (TextView)view.findViewById(R.id.descriptionLabel);
    }

    public void bindData(MyModel model) {
        titleLabel.setText(model.getTitle());
        descriptionLabel.setText(model.getDescription());
    }    
}

Elbette bu örnek, veri kaynağınızı (myData) bu şekilde bir bağdaştırıcı uygulamayı kolaylaştıracak şekilde oluşturduğunuzu varsayar. Örnek olarak, bir isim listesi ve adın ilk harfi her değiştiğinde (listenin alfabetik olarak sıralandığını varsayın) için bir başlık gösteren bir veri kaynağını nasıl oluşturacağımı göstereceğim - tıpkı bir kişilere benzer şekilde liste şöyle görünür:

// Assume names & descriptions are non-null and have the same length.
// Assume names are alphabetized
private void processDataSource(String[] names, String[] descriptions) {
    String nextFirstLetter = "";
    String currentFirstLetter;

    List<Object> data = new ArrayList<Object>();

    for (int i = 0; i < names.length; i++) {
        currentFirstLetter = names[i].substring(0, 1); // get the 1st letter of the name

        // if the first letter of this name is different from the last one, add a header row
        if (!currentFirstLetter.equals(nextFirstLetter)) {
            nextFirstLetter = currentFirstLetter;
            data.add(nextFirstLetter);
        }

        data.add(new MyModel(names[i], descriptions[i]));
    }

    myData = data.toArray();
}

Bu örnek oldukça spesifik bir sorunu çözmeye geliyor, ancak umarım bu size bir geri dönüşüm cihazında farklı sıra türlerinin nasıl işleneceği konusunda iyi bir genel bakış sağlar ve ihtiyaçlarınıza uyacak şekilde kendi kodunuzda gerekli uyarlamaları yapmanıza olanak tanır.


Oldukça harika ve bence bu, böyle bir sorunu çözmek için harika bir örnek Örnek Çözüm
Amt87

Yeniden inceleme içindeki farklı satırları bozmanın başka bir örneği: - stackoverflow.com/a/39972276/3946958
Ravindra Kushwaha

Olmalınames[i].substring(0, 1)
Kyle

1
Ayrıca, heterojen öğeler içeren geri dönüşümcü görünümleri için SpanSizeLookup'a da bakmak iyi bir fikirdir. stackoverflow.com/questions/26869312/…
Mahori

Bu kullanışlı. Bu cevaba dayanarak, enum kullanarak Adaptörde çoklu tip görünümü uygulamak için de bir fikrim var. Numaralandırma, onCreateViewHoldergörüntü sahibi oluşturmamıza yardımcı olacak bir yönteme sahip olacaktır . Daha fazla ayrıntı için paylaşımımı kontrol etmek isteyebilirsiniz: stackoverflow.com/questions/47245398/…
quangson91

114

İşin püf noktası, ViewHolder'ın alt sınıflarını oluşturmak ve ardından bunları yayınlamaktır.

public class GroupViewHolder extends RecyclerView.ViewHolder {
    TextView mTitle;
    TextView mContent;
    public GroupViewHolder(View itemView) {
        super (itemView);
        // init views...
    }
}

public class ImageViewHolder extends RecyclerView.ViewHolder {
    ImageView mImage;
    public ImageViewHolder(View itemView) {
        super (itemView);
        // init views...
    }
}

private static final int TYPE_IMAGE = 1;
private static final int TYPE_GROUP = 2;  

Ve sonra, çalışma zamanında şuna benzer bir şey yapın:

@Override
public int getItemViewType(int position) {
    // here your custom logic to choose the view type
    return position == 0 ? TYPE_IMAGE : TYPE_GROUP;
}

@Override
public void onBindViewHolder (ViewHolder viewHolder, int i) {

    switch (viewHolder.getItemViewType()) {

        case TYPE_IMAGE:
            ImageViewHolder imageViewHolder = (ImageViewHolder) viewHolder;
            imageViewHolder.mImage.setImageResource(...);
            break;

        case TYPE_GROUP:
            GroupViewHolder groupViewHolder = (GroupViewHolder) viewHolder;
            groupViewHolder.mContent.setText(...)
            groupViewHolder.mTitle.setText(...);
            break;
    }
}

Umarım yardımcı olur.


3
Bu sorunun doğrudan cevabıdır. Eksik olan tek parça, onCreateViewHolder'ı (ViewGroup parent, int viewType) geçersiz kılma ve viewType'a göre farklı görünüm türlerini kullanma ihtiyacıdır
user1928896

Yeniden inceleme içindeki farklı satırları bozmanın başka bir örneği: - stackoverflow.com/questions/39971350/…
Ravindra Kushwaha

1
Açma / kapama durumu değerlerinde görünüm tutucusu tabanı yerine genel bir çözüm var mı?
Vahid Ghadiri

33

Gil'e göre harika cevabı Gil tarafından açıklandığı gibi getItemViewType'ı geçersiz kılarak çözdüm. Cevabı harika ve doğru olarak işaretlenmeli. Her durumda, puana ulaşmak için kodu ekliyorum:

Geri dönüşüm adaptörünüzde:

@Override
public int getItemViewType(int position) {
    int viewType = 0;
    // add here your booleans or switch() to set viewType at your needed
    // I.E if (position == 0) viewType = 1; etc. etc.
    return viewType;
}

@Override
public FileViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == 0) {
        return new MyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.my_layout_for_first_row, parent, false));
    }

    return new MyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.my_other_rows, parent, false));
}

Bunu yaparak, hangi satır için herhangi bir özel düzeni ayarlayabilirsiniz!


18
Sadece küçük bir yorum: onCreateViewHolder'daki ikinci parametre, dizin değil, viewType olmalıdır. API'ye göre: developer.android.com/reference/android/support/v7/widget/… , int)
Mark Martinsson

ama ya kullanıcı o anda hızlı kaydırdığında bazı garip çıktılar alıyorum.
Rjz Satvara

15

Oldukça zor ama çok zor, sadece aşağıdaki kodu kopyalayın ve bitirdiniz

package com.yuvi.sample.main;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;


import com.yuvi.sample.R;

import java.util.List;

/**
 * Created by yubraj on 6/17/15.
 */

public class NavDrawerAdapter extends RecyclerView.Adapter<NavDrawerAdapter.MainViewHolder> {
    List<MainOption> mainOptionlist;
    Context context;
    private static final int TYPE_PROFILE = 1;
    private static final int TYPE_OPTION_MENU = 2;
    private int selectedPos = 0;
    public NavDrawerAdapter(Context context){
        this.mainOptionlist = MainOption.getDrawableDataList();
        this.context = context;
    }

    @Override
    public int getItemViewType(int position) {
        return (position == 0? TYPE_PROFILE : TYPE_OPTION_MENU);
    }

    @Override
    public MainViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch (viewType){
            case TYPE_PROFILE:
                return new ProfileViewHolder(LayoutInflater.from(context).inflate(R.layout.row_profile, parent, false));
            case TYPE_OPTION_MENU:
                return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.row_nav_drawer, parent, false));
        }
        return null;
    }

    @Override
    public void onBindViewHolder(MainViewHolder holder, int position) {
        if(holder.getItemViewType() == TYPE_PROFILE){
            ProfileViewHolder mholder = (ProfileViewHolder) holder;
            setUpProfileView(mholder);
        }
        else {
            MyViewHolder mHolder = (MyViewHolder) holder;
            MainOption mo = mainOptionlist.get(position);
            mHolder.tv_title.setText(mo.title);
            mHolder.iv_icon.setImageResource(mo.icon);
            mHolder.itemView.setSelected(selectedPos == position);
        }
    }

    private void setUpProfileView(ProfileViewHolder mholder) {

    }

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




public class MyViewHolder extends MainViewHolder{
    TextView tv_title;
    ImageView iv_icon;

    public MyViewHolder(View v){
        super(v);
        this.tv_title = (TextView) v.findViewById(R.id.tv_title);
        this.iv_icon = (ImageView) v.findViewById(R.id.iv_icon);
        v.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Redraw the old selection and the new
                notifyItemChanged(selectedPos);
                selectedPos = getLayoutPosition();
                notifyItemChanged(selectedPos);
            }
        });
    }
}
    public class ProfileViewHolder extends MainViewHolder{
        TextView tv_name, login;
        ImageView iv_profile;

        public ProfileViewHolder(View v){
            super(v);
            this.tv_name = (TextView) v.findViewById(R.id.tv_profile);
            this.iv_profile = (ImageView) v.findViewById(R.id.iv_profile);
            this.login = (TextView) v.findViewById(R.id.tv_login);
        }
    }

    public void trace(String tag, String message){
        Log.d(tag , message);
    }
    public class MainViewHolder extends  RecyclerView.ViewHolder {
        public MainViewHolder(View v) {
            super(v);
        }
    }


}

zevk almak !!!!


Viewholder1 cihazım, myLaout1.xml adında bir düzene ve içinde ScrollView'a sahiptir. Şimdi bu şeyi kaydırdığımda geri dönüşümcü görünümü kaydırılıyor. Viewholder1 içeriği nasıl kaydırılır
Ankesh kumar Jaisansaria

3

Tek bir RecyclerView üzerinde aşağıdaki yoldan birden fazla görüntü elde edebiliriz: -

Gradle bağımlılıkları bu nedenle aşağıdaki kodu ekleyin: -

compile 'com.android.support:cardview-v7:23.0.1'
compile 'com.android.support:recyclerview-v7:23.0.1'

XML'de RecyclerView

<android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

Aktivite Kodu

private RecyclerView mRecyclerView;
private CustomAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private String[] mDataset = {“Data - one ”, Data - two”,
    Showing data three”, Showing data four”};
private int mDatasetTypes[] = {DataOne, DataTwo, DataThree}; //view types
 
...
 
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mLayoutManager = new LinearLayoutManager(MainActivity.this);
mRecyclerView.setLayoutManager(mLayoutManager);
//Adapter is created in the last step
mAdapter = new CustomAdapter(mDataset, mDataSetTypes);
mRecyclerView.setAdapter(mAdapter);

İlk XML

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/cardview"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/ten"
    android:elevation="@dimen/hundered”
    card_view:cardBackgroundColor=“@color/black“>
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding=“@dimen/ten">
 
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=“Fisrt”
            android:textColor=“@color/white“ />
 
        <TextView
            android:id="@+id/temp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/ten"
            android:textColor="@color/white"
            android:textSize="30sp" />
    </LinearLayout>
 
</android.support.v7.widget.CardView>

İkinci XML

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/cardview"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/ten"
    android:elevation="100dp"
    card_view:cardBackgroundColor="#00bcd4">
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="@dimen/ten">
 
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=“DataTwo”
            android:textColor="@color/white" />
 
        <TextView
            android:id="@+id/score"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/ten"
            android:textColor="#ffffff"
            android:textSize="30sp" />
    </LinearLayout>
 
</android.support.v7.widget.CardView>

Üçüncü XML

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/cardview"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/ten"
    android:elevation="100dp"
    card_view:cardBackgroundColor="@color/white">
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="@dimen/ten">
 
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=“DataThree” />
 
        <TextView
            android:id="@+id/headline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/ten"
            android:textSize="25sp" />
 
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/ten"
            android:id="@+id/read_more"
            android:background="@color/white"
            android:text=“Show More/>
    </LinearLayout>
 
</android.support.v7.widget.CardView>

Şimdi adaptör yapma zamanı ve bu, aynı geri dönüştürücünün görünümünde farklı -2 görünümü göstermenin temelidir, bu nedenle lütfen bu kod odağını tam olarak kontrol edin: -

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
    private static final String TAG = "CustomAdapter";
 
    private String[] mDataSet;
    private int[] mDataSetTypes;
 
    public static final int dataOne = 0;
    public static final int dataTwo = 1;
    public static final int dataThree = 2;
 
 
    public static class ViewHolder extends RecyclerView.ViewHolder {
        public ViewHolder(View v) {
            super(v);
        }
    }
 
    public class DataOne extends ViewHolder {
        TextView temp;
 
        public DataOne(View v) {
            super(v);
            this.temp = (TextView) v.findViewById(R.id.temp);
        }
    }
 
    public class DataTwo extends ViewHolder {
        TextView score;
 
        public DataTwo(View v) {
            super(v);
            this.score = (TextView) v.findViewById(R.id.score);
        }
    }
 
    public class DataThree extends ViewHolder {
        TextView headline;
        Button read_more;
 
        public DataThree(View v) {
            super(v);
            this.headline = (TextView) v.findViewById(R.id.headline);
            this.read_more = (Button) v.findViewById(R.id.read_more);
        }
    }
 
 
    public CustomAdapter(String[] dataSet, int[] dataSetTypes) {
        mDataSet = dataSet;
        mDataSetTypes = dataSetTypes;
    }
 
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        View v;
        if (viewType == dataOne) {
            v = LayoutInflater.from(viewGroup.getContext())
                    .inflate(R.layout.weather_card, viewGroup, false);
 
            return new DataOne(v);
        } else if (viewType == dataTwo) {
            v = LayoutInflater.from(viewGroup.getContext())
                    .inflate(R.layout.news_card, viewGroup, false);
            return new DataThree(v);
        } else {
            v = LayoutInflater.from(viewGroup.getContext())
                    .inflate(R.layout.score_card, viewGroup, false);
            return new DataTwo(v);
        }
    }
 
    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int position) {
        if (viewHolder.getItemViewType() == dataOne) {
            DataOne holder = (DataOne) viewHolder;
            holder.temp.setText(mDataSet[position]);
        }
        else if (viewHolder.getItemViewType() == dataTwo) {
            DataThree holder = (DataTwo) viewHolder;
            holder.headline.setText(mDataSet[position]);
        }
        else {
            DataTwo holder = (DataTwo) viewHolder;
            holder.score.setText(mDataSet[position]);
        }
    }
 
    @Override
    public int getItemCount() {
        return mDataSet.length;
    }
 
   @Override
    public int getItemViewType(int position) {
        return mDataSetTypes[position];
    }
}

Daha fazla bilgi için bu bağlantıya da bakabilirsiniz .


ama bu iyi çalışıyor ama yukarıdan aşağıya hızlı kaydırdığımda ve tam tersi bazı garip çıktılar alıyorum ... verilerin doğru ayarlanmadığı anlamına gelir. çözümü nedir?
Rjz Satvara

2

getItemViewType()Metodu uygulamalısınız RecyclerView.Adapter. Bu yöntemin varsayılan onCreateViewHolder(ViewGroup parent, int viewType)uygulaması viewTypeolarak geri döner 0. Öncelikle, görüntüleme geri dönüşümü amacıyla konumdaki öğenin görüntüleme türüne ihtiyacınız vardır ve bunun için, öğenizin konumunu geri döndürecek olan getItemViewType()geçebileceğiniz yöntemi geçersiz viewTypekılmanız gerekir. Kod örneği aşağıda verilmiştir

@Override
public MyViewholder onCreateViewHolder(ViewGroup parent, int viewType) {
    int listViewItemType = getItemViewType(viewType);
    switch (listViewItemType) {
         case 0: return new ViewHolder0(...);
         case 2: return new ViewHolder2(...);
    }
}

@Override
public int getItemViewType(int position) {   
    return position;
}

// and in the similar way you can set data according 
// to view holder position by passing position in getItemViewType
@Override
public void onBindViewHolder(MyViewholder viewholder, int position) {
    int listViewItemType = getItemViewType(position);
    // ...
}

2

getItemViewType (int konumu) anahtardır

Kanımca, bu tür bir recyclerView oluşturmanın başlangıç ​​noktası, bu yöntemin bilgisidir. Bu yöntemin geçersiz kılınması isteğe bağlı olduğundan, varsayılan olarak RecylerView sınıfında görünmez ve bu da birçok geliştiricinin (ben dahil) nereden başlayacağını merak etmesine neden olur. Bu yöntemin var olduğunu öğrendikten sonra, böyle bir RecyclerView oluşturmak çok kolay olacaktır.

görüntü açıklamasını buraya girin

Nasıl yapılır ?

RecyclerViewHerhangi bir sayıda farklı Görünüm (ViewHolders) ile bir oluşturabilirsiniz . Ancak daha iyi okunabilirlik için RecyclerViewiki ile bir örnek alalım Viewholders.
Bu 3 basit adımı hatırlayın ve gitmeniz iyi olacak.

  • Public int'i geçersiz kıl getItemViewType(int position)
  • OnCreateViewHolder ViewType() yöntemine göre farklı ViewHolders döndürür
  • Görünümü itemViewType onBindViewHolder()yöntemine göre doldurun

    İşte sizin için bir kod parçası

    public class YourListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    
        private static final int LAYOUT_ONE= 0;
        private static final int LAYOUT_TWO= 1;
    
        @Override
        public int getItemViewType(int position)
        {
            if(position==0)
               return LAYOUT_ONE;
            else
               return LAYOUT_TWO;
        }
    
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    
            View view =null;
            RecyclerView.ViewHolder viewHolder = null;
    
            if(viewType==LAYOUT_ONE)
            {
               view = LayoutInflater.from(parent.getContext()).inflate(R.layout.one,parent,false);
               viewHolder = new ViewHolderOne(view);
            }
            else
            {
               view = LayoutInflater.from(parent.getContext()).inflate(R.layout.two,parent,false);
               viewHolder= new ViewHolderTwo(view);
            }
    
            return viewHolder;
        }
    
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
    
           if(holder.getItemViewType()== LAYOUT_ONE)
           {
               // Typecast Viewholder 
               // Set Viewholder properties 
               // Add any click listener if any 
           }
           else {
    
               ViewHolderOne vaultItemHolder = (ViewHolderOne) holder;
               vaultItemHolder.name.setText(displayText);
               vaultItemHolder.name.setOnClickListener(new View.OnClickListener() {
                   @Override
                   public void onClick(View v) {
                       .......
                   }
               });
    
           }
    
       }
    
       /****************  VIEW HOLDER 1 ******************//
    
       public class ViewHolderOne extends RecyclerView.ViewHolder {
    
           public TextView name;
    
           public ViewHolderOne(View itemView) {
           super(itemView);
           name = (TextView)itemView.findViewById(R.id.displayName);
           }
       }
    
    
      //****************  VIEW HOLDER 2 ******************//
    
      public class ViewHolderTwo extends RecyclerView.ViewHolder{
    
           public ViewHolderTwo(View itemView) {
           super(itemView);
    
               ..... Do something
           }
      }
    }

GitHub Kodu:

Burada, birden çok ViewHolders ile bir RecyclerView uyguladığım bir proje .


Ya aynısı ama aynı zamanda birden fazla veri kümesine sahip olmak?
esQmo_

Ne demek istiyorsun? @esQmo_
Rohit Singh

Demek istediğim, her vieholder aynı zamanda farklı veri kümesine (veri kaynağı) sahipse?
esQmo_

1

ItemViewType'ı iade edip kullanabilirsiniz. Aşağıdaki koda bakın:

@Override
public int getItemViewType(int position) {

    Message item = messageList.get(position);
    // return my message layout
    if(item.getUsername() == Message.userEnum.I)
        return R.layout.item_message_me;
    else
        return R.layout.item_message; // return other message layout
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
    View view = LayoutInflater.from(viewGroup.getContext()).inflate(viewType, viewGroup, false);
    return new ViewHolder(view);
}

1

Kitaplığı kullanabilirsiniz: https://github.com/vivchar/RendererRecyclerViewAdapter

mRecyclerViewAdapter = new RendererRecyclerViewAdapter(); /* included from library */
mRecyclerViewAdapter.registerRenderer(new SomeViewRenderer(SomeModel.TYPE, this));
mRecyclerViewAdapter.registerRenderer(...); /* you can use several types of cells */

Her öğe için bir ViewRenderer, ViewHolder, SomeModel uygulamanız gerekir:

ViewHolder - geri dönüşümcü görünümünün basit bir görüntü tutucusudur.

SomeModel - ItemModelarayüzlü modeliniz

public class SomeViewRenderer extends ViewRenderer<SomeModel, SomeViewHolder> {

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

Daha fazla ayrıntı için belgelere bakabilirsiniz.


0

Bu kitaplığı kullanabilirsiniz:
https://github.com/kmfish/MultiTypeListViewAdapter (benim tarafımdan yazılmıştır)

  • Bir hücrenin kodunu daha iyi kullanın
  • Daha iyi genişleme
  • Daha iyi ayırma

Kurulum adaptörü:

adapter = new BaseRecyclerAdapter();
adapter.registerDataAndItem(TextModel.class, LineListItem1.class);
adapter.registerDataAndItem(ImageModel.class, LineListItem2.class);
adapter.registerDataAndItem(AbsModel.class, AbsLineItem.class);

Her satır öğesi için:

public class LineListItem1 extends BaseListItem<TextModel, LineListItem1.OnItem1ClickListener> {

    TextView tvName;
    TextView tvDesc;


    @Override
    public int onGetLayoutRes() {
        return R.layout.list_item1;
    }

    @Override
    public void bindViews(View convertView) {
        Log.d("item1", "bindViews:" + convertView);
        tvName = (TextView) convertView.findViewById(R.id.text_name);
        tvDesc = (TextView) convertView.findViewById(R.id.text_desc);

        tvName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != attachInfo) {
                    attachInfo.onNameClick(getData());
                }
            }
        });
        tvDesc.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != attachInfo) {
                    attachInfo.onDescClick(getData());
                }
            }
        });

    }

    @Override
    public void updateView(TextModel model, int pos) {
        if (null != model) {
            Log.d("item1", "updateView model:" + model + "pos:" + pos);
            tvName.setText(model.getName());
            tvDesc.setText(model.getDesc());
        }
    }

    public interface OnItem1ClickListener {
        void onNameClick(TextModel model);
        void onDescClick(TextModel model);
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.