Создание ViewHolders для ListView с различными макетами элементов

У меня есть ListView с разными макетами для разных элементов. Некоторые элементы являются разделителями. Некоторые элементы разные, потому что они содержат разные данные и т. Д.

Я хочу реализовать ViewHolders, чтобы ускорить процесс getView, но я не совсем уверен, как это сделать. В разных макетах есть разные части данных (что затрудняет именование) и разное количество просмотров, которые я хочу использовать.

Как мне это сделать?

Лучшая идея, которую я могу придумать, – создать общий ViewHolder с элементами X, где X – количество просмотров в макете элементов с наибольшим количеством из них. Для других представлений с небольшим количеством представлений я просто использую подраздел этих переменных в ViewHolder. Так сказать, у меня есть 2 макета, которые я использую для двух разных предметов. У одного есть 3 TextViews, а у другого – 1. Я бы создал ViewHolder с 3 переменными TextView и использовал только один из них для моего другого элемента. Моя проблема в том, что это может стать действительно уродливым и выглядеть очень хаки; Особенно когда макет элемента может иметь много видов для разных типов.

Вот очень простой getView:

@Override public View getView(int position, View convertView, ViewGroup parent) { MyHolder holder; View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.layout_mylistlist_item, parent, false); holder = new MyHolder(); holder.text = (TextView) v.findViewById(R.id.mylist_itemname); v.setTag(holder); } else { holder = (MyHolder)v.getTag(); } MyListItem myItem = m_items.get(position); // set up the list item if (myItem != null) { // set item text if (holder.text != null) { holder.text.setText(myItem.getItemName()); } } // return the created view return v; } 

Предположим, у меня были разные типы макетов строк, я мог бы иметь ViewHolder для каждого типа строки. Но какой тип я бы назвал «держателем» на вершине? Или я могу объявить держатель для каждого типа, а затем использовать его для типа строки, в которой я включен.

Solutions Collecting From Web of "Создание ViewHolders для ListView с различными макетами элементов"

ListView имеет встроенную систему управления типом. В вашем адаптере у вас есть несколько типов элементов, каждый со своим видом и макетом. Переопределяя getItemViewType, чтобы вернуть тип данных заданной позиции, ListView имеет обязательную силу, чтобы передать правильное преобразование для этого типа данных. Затем в вашем методе getView просто проверьте тип данных и используйте оператор switch для обработки каждого типа по-разному.

Каждый тип макета должен иметь свой собственный зритель для определения ясности и удобства обслуживания. Назовите ViewHolders что-то, связанное с каждым типом данных, чтобы все было прямолинейно.

Попытка пересечь все в один ViewHolder просто не стоит усилий.

Изменить пример

 @Override public View getView(int position, View convertView, ViewGroup parent) { int viewType = this.getItemViewType(position); switch(viewType) { case TYPE1: Type1Holder holder1; View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater)getContext().getSystemService (Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.layout_mylistlist_item_type_1, parent, false); holder1 = new Type1Holder (); holder1.text = (TextView) v.findViewById(R.id.mylist_itemname); v.setTag(holder1); } else { holder1 = (Type1Holder)v.getTag(); } MyListItem myItem = m_items.get(position); // set up the list item if (myItem != null) { // set item text if (holder1.text != null) { holder1.text.setText(myItem.getItemName()); } } // return the created view return v; case TYPE2: Type2Holder holder2; View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.layout_mylistlist_item_type_2, parent, false); holder2 = new Type2Holder (); holder2.text = (TextView) v.findViewById(R.id.mylist_itemname); holder2.icon = (ImageView) v.findViewById(R.id.mylist_itemicon); v.setTag(holder1); } else { holder2 = (Type2Holder)v.getTag(); } MyListItem myItem = m_items.get(position); // set up the list item if (myItem != null) { // set item text if (holder2.text != null) { holder2.text.setText(myItem.getItemName()); } if(holder2.icon != null) holder2.icon.setDrawable(R.drawable.icon1); } // return the created view return v; default: //Throw exception, unknown data type } } 

Другой пример.

Открытый класс CardArrayAdapter расширяет ArrayAdapter {

 public CardArrayAdapter(Context context) { super(context, R.layout.adapter_card); } @Override public View getView(int position, View view, ViewGroup parent) { final Card card = getItem(position); ViewHolder holder; //if (view != null) { //holder = (ViewHolder) view.getTag(); //} else { Log.d("card.important?", card.name + " = " + Boolean.toString(card.important)); if(card.important) { view = LayoutInflater.from(getContext()).inflate(R.layout.adapter_card_important, parent, false); }else { view = LayoutInflater.from(getContext()).inflate(R.layout.adapter_card, parent, false); } holder = new ViewHolder(view); view.setTag(holder); //} // IMG Picasso.with(getContext()) .load(card.logo) .placeholder(R.drawable.ic_phonebook) .error(R.drawable.ic_phonebook) .fit() .centerCrop() .transform(new CircleTransform()) .into(holder.logo); holder.name.setText(card.name); if(card.important) { holder.category.setVisibility(View.VISIBLE); if (card.category.equals("airline")) { card.category = "airlines"; } int id = getContext().getResources().getIdentifier(card.category, "string", getContext().getPackageName()); holder.category.setText(getContext().getResources().getString(id)); }else { holder.category.setVisibility(View.GONE); } holder.tagline.setText(card.tagline); holder.favorite.setChecked(card.favorite); holder.favorite.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { card.favorite = ((CheckBox) v).isChecked(); card.save(); } }); return view; } static class ViewHolder { @InjectView(R.id.logo) ImageView logo; @InjectView(R.id.name) TextView name; @InjectView(R.id.category) TextView category; @InjectView(R.id.tagline) TextView tagline; @InjectView(R.id.favorite) CheckBox favorite; public ViewHolder(View view) { ButterKnife.inject(this, view); } } 

}