Android:不同项目的列表视图的xml布局
我正在阅读本教程http://android.amberfog.com/?p=296 。 我想要创build一个ListView不同types的行。 我知道如何创build适配器,但是xml布局呢? 所以我定义了一个这样的XML布局:
<ListView/> <TextView android:id="@+id/id1" /> <TextView android:id="@+id/id2" /> <ImageView android:id="@+id/id3" /> <TextView android:id="@+id/id4" />
如果一行只使用布局的一些元素(只有一些文本浏览),另一行可能使用其他元素,会是一个问题(性能)? 我不明白,如果我是正确的方式来定义XML或如果我必须为每种types的行创build不同的布局。
先谢谢你
编辑:现在我有一个零点例外。
来自适配器的java代码:
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; int type = getItemViewType(position); if (convertView == null) { holder = new ViewHolder(); convertView = mInflater.inflate(R.layout.listview_main, null); holder.textView_title = (TextView)convertView.findViewById(R.id.listview1); convertView.setTag(holder); } else { holder = (ViewHolder)convertView.getTag(); } **holder.textView_title.setText("aaaa");** //NULL POINT EXCEPTION HERE return convertView;
}
class ViewHolder { public TextView textView_title; }
xml 1:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="left" android:layout_margin="0dp"> <!-- android:background="#0094ff" --> <ListView android:id="@id/android:list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:fastScrollEnabled="true" android:scrollbarStyle="insideInset" android:textFilterEnabled="false" android:divider="@null" android:layout_margin="0dp" android:paddingTop="0dp" android:paddingBottom="0dp" android:paddingLeft="15dp" android:paddingRight="22dp"/> </LinearLayout>
XML2
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="left" android:layout_margin="0dp"> <TextView android:id="@+id/listview1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingTop="7dp" android:paddingBottom="0dp" android:paddingLeft="0dp" android:paddingRight="0dp" android:textSize="18sp" android:textColor="#000000" android:lines="1"> </TextView> </LinearLayout>
您需要重写getViewItemType
和getViewTypeCount
。 您还需要有自定义布局。
getItemViewType(int position)
– 根据位置返回您应该使用哪种布局types的信息。
你应该看看链接中的video。
http://www.youtube.com/watch?v=wDBM6wVEO70
private static final int TYPE_ITEM1 = 0; private static final int TYPE_ITEM2 = 1; private static final int TYPE_ITEM3 = 2;
然后
int type; @Override public int getItemViewType(int position) { if (position== 0){ type = TYPE_ITEM1; } else if (position == 1){ type = TYPE_ITEM2; } else { type= TYPE_ITEM3 ; } return type; } @Override public int getViewTypeCount() { return 3; } @Override public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; LayoutInflater inflater = null; int type = getItemViewType(position); // instead of if else you can use a case if (row == null) { if (type == FIRST_TYPE) { //infalte layout of type1 } if (type == SECOND_TYPE) { //infalte layout of type2 } else { //infalte layout of normaltype } }
- 我刚刚解决了为不同的行创build不同的布局的问题。
- 在相应的不同xml文件中定义所有不同的布局。
- 重写getViewTypeCount()方法并从中返回已定义布局的数目。
- 重写getItemViewType()方法,并根据列表视图中元素的“位置”与build议的xml布局之间的关系定义条件并返回相应的整数值。
- 通过在getView()方法中调用getItemViewType()方法,我们可以得到与布局相对应的数字,然后用相应的xml布局膨胀convertView。 然后通过使用findViewById(),您可以将值传入在ViewHolder类和setText中定义的TextView类的对象,或者您想要使用的任何操作都可以进一步完成。 尽可能简单。 假设我们有4种types的布局和4个XML文件,分别命名为element1,element2,element3,element4和两个普通的textview标识为text1,text2。
@Override public int getItemViewType(int position) { if (position % 4 == 0) { return 0; } else if (position % 4 == 1) { return 1; } else if (position % 4 == 2) { return 2; } return 3; }
public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; int type = getItemViewType(position); if (convertView == null) { switch (type) { case 0: { convertView = mInflater.inflate(R.layout.element1, null); break; } case 1: { convertView = mInflater.inflate(R.layout.element2, null); break; } case 2: { convertView = mInflater.inflate(R.layout.element3, null); break; } case 3: { convertView = mInflater.inflate(R.layout.element4, null); break; } } holder = new ViewHolder(); holder.txt1 = (TextView) convertView.findViewById(R.id.text1); holder.txt2 = (TextView) convertView.findViewById(R.id.text2); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } String rowItem = null; rowItem = rowItems[position]; holder.txt1.setText(rowItem); rowItem = rowItems[position+1]; holder.txt1.setText(rowItem); return convertView; } private class ViewHolder { TextView txt1, txt2; }
这可能是一个错误的方法来做到这一点。 如果ListView中只有一个组件,那么使用简单的适配器,否则使用单独的XML作为列表行的自定义适配器。
示例代码:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.listhistory); initcomponents(); ArrayList<HashMap<String, String>> alist = new ArrayList<HashMap<String, String>>(); for (int i = 1; i < 20; i++) { HashMap<String, String> hmap = new HashMap<String, String>(); hmap.put("date", "" + i + "/13"); hmap.put("restaurant", "Restaurant" + i); hmap.put("distance", "" + (i * 100) + "kms"); alist.add(hmap); } final CustomListAdapter adapter = new CustomListAdapter(this, R.layout.listitemhistory, alist); list.setAdapter(adapter); } private void initcomponents() { list = (ListView) findViewById(R.id.history_lst_list); } public void backButtonClick(View v) { finish(); } class CustomListAdapter extends ArrayAdapter<HashMap<String, String>> { Context context; int textViewResourceId; ArrayList<HashMap<String, String>> alist; public CustomListAdapter(Context context, int textViewResourceId, ArrayList<HashMap<String, String>> alist) { super(context, textViewResourceId); this.context = context; this.alist = alist; this.textViewResourceId = textViewResourceId; } public int getCount() { return alist.size(); } public View getView(int pos, View convertView, ViewGroup parent) { Holder holder = null; LayoutInflater inflater = ((Activity) context) .getLayoutInflater(); convertView = inflater.inflate(R.layout.listitemhistory, parent, false); holder = new Holder(); holder.date = (TextView) convertView .findViewById(R.id.listitemhistory_txt_date); holder.restaurant = (TextView) convertView .findViewById(R.id.listitemhistory_txt_restaurant); holder.distance = (TextView) convertView .findViewById(R.id.listitemhistory_txt_distance); holder.lin_background = (LinearLayout) convertView .findViewById(R.id.history_lin_background); convertView.setTag(holder); holder = (Holder) convertView.getTag(); holder.date.setText(alist.get(pos).get("date")); holder.restaurant.setText(alist.get(pos).get("restaurant")); holder.distance.setText(alist.get(pos).get("distance")); return convertView; } class Holder { TextView date, restaurant, distance; LinearLayout lin_background; } }
这不会是一个问题。 但我认为你得到的教程是错误的。
你需要为一行定义一个布局。
如果您希望行可以包含文本或图像,则需要将两个视图添加到布局。
现在在你的适配器中,你在哪里填充你的列表,你决定要设置哪个项目。
所以可以说,你有2个string和一个图像。
所以你设置了前两行的文本,并将图像添加到第三行。 你不必为自己预定义每一行,因为我猜这就是你想要做的。