В текущем проекте у меня есть ListView с пользовательским адаптером. Тем не менее, теперь я заинтересован в добавлении нескольких типов представлений в свой ListView, но после нескольких попыток я не смог добавить два источника кода вместе, чтобы успешно их интегрировать.
Статья в ListView с несколькими представлениями: статья ListView для нескольких видов
Пользовательский адаптер в моем текущем коде извлекает данные из другого класса с именем getData, на который ссылаются “данные”.
Код из статьи (ListView с несколькими видами):
public class MultipleItemsList extends ListActivity {
private MyCustomAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new MyCustomAdapter();
for (int i = 1; i < 50; i++) {
mAdapter.addItem("item " + i);
if (i % 4 == 0) {
mAdapter.addSeparatorItem("separator " + i);
}
}
setListAdapter(mAdapter);
}
private class MyCustomAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private ArrayList mData = new ArrayList();
private LayoutInflater mInflater;
private TreeSet mSeparatorsSet = new TreeSet();
public MyCustomAdapter() {
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
public void addSeparatorItem(final String item) {
mData.add(item);
// save separator position
mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
@Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public String getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
System.out.println("getView " + position + " " + convertView + " type = " + type);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.item1, null);
holder.textView = (TextView)convertView.findViewById(R.id.text);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.item2, null);
holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textView.setText(mData.get(position));
return convertView;
}
}
public static class ViewHolder {
public TextView textView;
}
}
Текущий код (ListView с пользовательским адаптером):
FragmentA.java
package com.example.newsapp;
public class FragmentA extends Fragment{
getData data = getData.getMyData();
public Integer ArticleID;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View V = inflater.inflate(R.layout.fragment_a, container, false);
ListView listView = (ListView)V.findViewById(R.id.list)
CustomList adapter = new
CustomList(getActivity(), data.Headline.toArray(new String[data.Headline.size()]), data.Description.toArray(new String[data.Description.size()]), data.BitmapList.toArray(new Bitmap[data.BitmapList.size()]), data.ArticleID.toArray(new Integer[data.ArticleID.size()]));
listView.setAdapter(adapter);
listView.setOnItemClickListener(this); //Removed on click item event code.
return V;
}
CustomList.java
package com.example.newsapp;
public class CustomList extends ArrayAdapter<String>{
private final Activity context;
private final String[] titleId;
private final String[] descriptionId;
private final Bitmap[] pictureid;
public CustomList(Activity context,
String[] Headline, String[] Description, Bitmap[] BitmapList, Integer[] ArticleID) {
super(context, R.layout.single_row, Headline);
this.context = context;
this.titleId = Headline;
this.descriptionId = Description;
this.pictureid = BitmapList;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView= inflater.inflate(R.layout.single_row, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.tvTitle);
TextView txtDescription = (TextView) rowView.findViewById(R.id.tvDescription);
ImageView imageView = (ImageView) rowView.findViewById(R.id.ivIcon);
txtTitle.setText(titleId[position]);
txtDescription.setText(descriptionId[position]);
imageView.setImageBitmap(pictureid[position]);
return rowView;
}
}
Редактировать:
public class CustomList extends ArrayAdapter<String>{
private final Activity context;
private final String[] titleId;
private final String[] descriptionId;
private final Bitmap[] pictureid;
public CustomList(Activity context,
String[] Headline, String[] Description, Bitmap[] BitmapList, Integer[] ArticleID) {
super(context, R.layout.single_row, Headline);
this.context = context;
this.titleId = Headline;
this.descriptionId = Description;
this.pictureid = BitmapList;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
int viewType = getItemViewType(position);
View rowView = null;
switch(viewType) {
case 0:
LayoutInflater inflater = context.getLayoutInflater();
rowView= inflater.inflate(R.layout.single_row, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.tvTitle);
TextView txtDescription = (TextView) rowView.findViewById(R.id.tvDescription);
ImageView imageView = (ImageView) rowView.findViewById(R.id.ivIcon);
txtTitle.setText(titleId[position]);
txtDescription.setText(descriptionId[position]);
imageView.setImageBitmap(pictureid[position]);
case 1:
LayoutInflater inflater2 = context.getLayoutInflater();
rowView= inflater2.inflate(R.layout.single_row_loadmore, null, true);
}
return rowView;
}
@Override
public int getViewTypeCount() {
return 2; // TODO make this a static final
}
@Override
public int getItemViewType(int position) {
return position % 2; // 0 or 1
}
}
Во-первых, немного в стороне: вы должны создать класс, который инкапсулирует заголовок, описание и т.д. И использовать массив/коллекцию этих объектов для поддержки вашего адаптера. Это будет намного проще, чем управлять множеством разрозненных массивов вещей, особенно если однажды вы решите, что вам нужен другой атрибут статьи (например, ее категория).
class Article {
int id;
String headline;
String description;
Bitmap picture;
}
Что касается вашего ListView, волшебство происходит в методах getItemViewType()
и getViewTypeCount()
. В getViewTypeCount()
вы возвращаете максимальное количество типов строк – в статье, которую вы опубликовали, используется два типа строк, и поэтому возвращает 2
. В getItemViewType()
вы возвращаете значение между нулем и (viewTypeCount – 1) – в статье его реализация может возвращать 0
или 1
потому что его viewTypeCount равен 2
.
Как вы решаете, какой тип строки относится к каждому элементу, полностью зависит от вас. Если, например, вы хотели просто чередовать типы вида в каждой строке, вы можете сделать это:
@Override
public int getViewTypeCount() {
return 2; // TODO make this a static final
}
@Override
public int getItemViewType(int position) {
return position % 2; // 0 or 1
}
В других приложениях вы, вероятно, проверите элемент в указанной позиции, чтобы помочь вам определить, что должно быть возвращено в getItemViewtype()
.
Причина, по которой эта функциональность существует, заключается в том, что getView()
предоставляет параметр (называемый convertView
), который представляет собой строку, которая была переработана. Чтобы предоставить вам соответствующий convertView
, ListView должен сначала узнать, какой тип строки он был. Когда вы хотите реализовать getView()
для адаптера с несколькими типами строк, он обычно выглядит примерно так:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int viewType = getItemViewType(position);
switch(viewType) {
case 0:
return setUpOneViewType(position, convertView, parent);
case 1:
return setUpAnotherViewType(position, convertView, parent);
}
}
Обратите внимание, что случаи для оператора switch соответствуют возможным значениям, которые могут быть возвращены из getItemViewType()
. Это могут быть static final
члены.
Я настоятельно рекомендую посмотреть World of ListView. Это видео охватывает эту тему, а также как правильно использовать convertView
в реализации адаптера.