การจัดการตรรกะของแถว / ส่วนที่คล้ายกับ UITableView ของ iOS นั้นไม่ง่ายอย่างใน Android เหมือนกับใน iOS อย่างไรก็ตามเมื่อคุณใช้ RecyclerView ความยืดหยุ่นของสิ่งที่คุณทำได้นั้นยิ่งใหญ่กว่ามาก
ในตอนท้ายทั้งหมดนี้เป็นข้อมูลเกี่ยวกับวิธีที่คุณทราบว่าคุณกำลังแสดงมุมมองประเภทใดในอะแดปเตอร์ เมื่อคุณเข้าใจแล้วก็ควรจะแล่นเรือได้ง่าย (ไม่จริง แต่อย่างน้อยคุณก็จะจัดเรียงได้)
อะแดปเตอร์แสดงวิธีการสองวิธีที่คุณควรแทนที่:
getItemViewType(int position)
การใช้งานเริ่มต้นของวิธีนี้จะคืนค่า 0 เสมอแสดงว่ามีมุมมองเพียง 1 ประเภท ในกรณีของคุณไม่เป็นเช่นนั้นดังนั้นคุณจะต้องหาวิธียืนยันว่าแถวใดตรงกับประเภทมุมมองใด ซึ่งแตกต่างจาก iOS ซึ่งจัดการสิ่งนี้ให้คุณด้วยแถวและส่วนที่นี่คุณจะมีดัชนีเพียงรายการเดียวที่ต้องพึ่งพาและคุณจะต้องใช้ทักษะของนักพัฒนาเพื่อที่จะทราบว่าตำแหน่งใดสัมพันธ์กับส่วนหัวของส่วนและเมื่อใดที่สัมพันธ์กับ แถวปกติ
createViewHolder(ViewGroup parent, int viewType)
คุณต้องแทนที่วิธีนี้อยู่ดี แต่โดยปกติแล้วผู้คนจะเพิกเฉยต่อพารามิเตอร์ viewType ตามประเภทมุมมองคุณจะต้องขยายทรัพยากรการจัดวางที่ถูกต้องและสร้างตัวยึดมุมมองของคุณตามนั้น RecyclerView จะจัดการการรีไซเคิลมุมมองประเภทต่างๆเพื่อหลีกเลี่ยงการปะทะกันของมุมมองประเภทต่างๆ
หากคุณกำลังวางแผนที่จะใช้ LayoutManager เริ่มต้นเช่นLinearLayoutManager
คุณควรจะไป หากคุณกำลังวางแผนที่จะใช้ LayoutManager ของคุณเองคุณจะต้องทำงานให้หนักขึ้นเล็กน้อย API เดียวที่คุณต้องใช้จริงๆคือfindViewByPosition(int position)
ให้มุมมองที่กำหนดในตำแหน่งหนึ่ง ๆ เนื่องจากคุณอาจต้องการจัดวางให้แตกต่างกันไปขึ้นอยู่กับประเภทของมุมมองนี้คุณจึงมีตัวเลือกดังนี้
โดยปกติเมื่อใช้รูปแบบ ViewHolder คุณจะตั้งค่าแท็กของมุมมองด้วยตัวยึดมุมมอง คุณสามารถใช้สิ่งนี้ระหว่างรันไทม์ในตัวจัดการโครงร่างเพื่อค้นหาว่ามุมมองเป็นประเภทใดโดยการเพิ่มฟิลด์ในตัวยึดมุมมองที่แสดงสิ่งนี้
เนื่องจากคุณจะต้องมีฟังก์ชันที่กำหนดว่าตำแหน่งใดสัมพันธ์กับประเภทมุมมองใดคุณจึงอาจทำให้วิธีนี้สามารถเข้าถึงได้ทั่วโลก (อาจเป็นคลาสเดี่ยวที่จัดการข้อมูล?) จากนั้นคุณสามารถสืบค้นวิธีการเดียวกันตาม ตำแหน่ง.
นี่คือตัวอย่างโค้ด:
// 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;
}
}
นี่คือตัวอย่างลักษณะของผู้ถือมุมมองเหล่านี้:
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());
}
}
แน่นอนว่าตัวอย่างนี้ถือว่าคุณได้สร้างแหล่งข้อมูล (myData) ของคุณด้วยวิธีที่ทำให้ง่ายต่อการใช้งานอะแดปเตอร์ด้วยวิธีนี้ ตัวอย่างเช่นฉันจะแสดงให้คุณเห็นว่าฉันสร้างแหล่งข้อมูลอย่างไรซึ่งจะแสดงรายชื่อและส่วนหัวทุกครั้งที่ตัวอักษรตัวที่ 1 ของชื่อเปลี่ยนไป (สมมติว่ารายการเรียงตามตัวอักษร) - คล้ายกับที่ติดต่อ รายการจะมีลักษณะดังนี้:
// 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();
}
ตัวอย่างนี้มาเพื่อแก้ปัญหาที่ค่อนข้างเฉพาะเจาะจง แต่ฉันหวังว่านี่จะช่วยให้คุณเห็นภาพรวมที่ดีเกี่ยวกับวิธีจัดการแถวประเภทต่างๆในเครื่องรีไซเคิลและช่วยให้คุณทำการปรับเปลี่ยนที่จำเป็นในรหัสของคุณเองเพื่อให้เหมาะกับความต้องการของคุณ