Menangani logika baris / bagian yang mirip dengan UITableView di iOS tidak sesederhana di Android seperti di iOS, namun, ketika Anda menggunakan RecyclerView - fleksibilitas yang dapat Anda lakukan jauh lebih besar.
Pada akhirnya, ini semua tentang bagaimana Anda mengetahui jenis tampilan yang Anda tampilkan di Adaptor. Setelah Anda mengetahuinya, itu harus mudah berlayar (tidak juga, tapi setidaknya Anda akan memiliki yang diurutkan).
Adaptor memaparkan dua metode yang harus Anda timpa:
getItemViewType(int position)
Implementasi default metode ini akan selalu menghasilkan 0, menunjukkan bahwa hanya ada 1 jenis tampilan. Dalam kasus Anda, tidak demikian halnya, dan Anda perlu menemukan cara untuk menegaskan baris mana yang sesuai dengan tipe tampilan mana. Tidak seperti iOS, yang mengelola ini untuk Anda dengan baris dan bagian, di sini Anda hanya akan memiliki satu indeks untuk diandalkan, dan Anda harus menggunakan keterampilan pengembang Anda untuk mengetahui kapan posisi berkorelasi dengan header bagian, dan kapan itu berkorelasi dengan baris normal.
createViewHolder(ViewGroup parent, int viewType)
Anda perlu mengganti metode ini, tetapi biasanya orang mengabaikan parameter viewType. Menurut jenis tampilan, Anda harus mengembang sumber daya tata letak yang benar dan membuat pemegang tampilan Anda sesuai. RecyclerView akan menangani daur ulang berbagai jenis tampilan dengan cara yang menghindari bentrok dari berbagai jenis tampilan.
Jika Anda berencana menggunakan LayoutManager default, seperti LinearLayoutManager
, Anda sebaiknya melakukannya. Jika Anda berencana membuat implementasi LayoutManager Anda sendiri, Anda harus bekerja sedikit lebih keras. Satu-satunya API yang benar-benar harus Anda kerjakan adalah findViewByPosition(int position)
yang memberikan tampilan tertentu pada posisi tertentu. Karena Anda mungkin ingin meletakkannya secara berbeda tergantung pada jenis tampilan ini, Anda memiliki beberapa opsi:
Biasanya saat menggunakan pola ViewHolder, Anda mengatur tag view dengan view view. Anda bisa menggunakan ini selama runtime di manajer tata letak untuk mengetahui apa jenis tampilan dengan menambahkan bidang di tempat tampilan yang mengekspresikan ini.
Karena Anda akan memerlukan fungsi yang menentukan posisi mana yang berkorelasi dengan tipe tampilan mana, Anda mungkin juga membuat metode ini dapat diakses secara global (mungkin kelas tunggal yang mengelola data?), Dan kemudian Anda dapat dengan mudah menanyakan metode yang sama sesuai dengan Posisinya.
Berikut ini contoh kode:
// 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;
}
}
Berikut ini contoh tampilan pemegang tampilan:
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());
}
}
Tentu saja, sampel ini mengasumsikan Anda telah membangun sumber data Anda (myData) dengan cara yang membuatnya mudah untuk mengimplementasikan adaptor dengan cara ini. Sebagai contoh, saya akan menunjukkan kepada Anda bagaimana saya akan membangun sumber data yang menunjukkan daftar nama, dan header untuk setiap kali huruf pertama dari nama tersebut berubah (anggaplah daftar itu disusun menurut abjad) - mirip dengan cara kontak daftar akan terlihat seperti:
// 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();
}
Contoh ini datang untuk menyelesaikan masalah yang cukup spesifik, tetapi saya harap ini memberi Anda tinjauan yang baik tentang bagaimana menangani jenis baris yang berbeda dalam pendaur ulang, dan memungkinkan Anda membuat adaptasi yang diperlukan dalam kode Anda sendiri agar sesuai dengan kebutuhan Anda.