在ScrollView 里面包含有一个ListView时,ListView只能显示一行多一点。
原因是ScrollView无法计算ListView的高度。
解决办法是在代码中计算ListView的高度。
ListView listview = (ListView) findViewById(R.id.lv);
listview.setAdapter(adapter);
setListViewBaseOnChild(listview);
private void setListViewBaseOnChild(ListView lv) {
// TODO Auto-generated method stub
ListAdapter adapter = lv.getAdapter();
//itemTotalHeight
int itemTotalHeight = 0;
for(int i=0;i<adapter.getCount();i++){
View listItem = adapter.getView(i, null, lv);
listItem.measure(0, 0);
itemTotalHeight +=listItem.getMeasuredHeight();
}
//dividedTotalHeight
int dividedTotalHeight = (adapter.getCount() - 1)*lv.getDividerHeight();
ViewGroup.LayoutParams params = lv.getLayoutParams();
params.height = itemTotalHeight + dividedTotalHeight;
lv.setLayoutParams(params);
}
这种解决方法可以正常显示ListView了,但会导致ListView滑动复用机制消失,有多少item会一次性全部创建,当item很多时,会造成内存等性能问题。
ArrayAdapter
当data是数组或者List时,用ArrayAdapter,指定一个TextView显示数组或者List中对象的toString返回的String。
ListActivity、ListFragment
默认含有一个ListView,通过setListAdapter(adapter)设置ListView的adapter。
可以让ListActivity使用自定义的ListView,将ListView的 id 设置成 android:id="@android:id/list" ,然后setContentView(layout)
当ListView为空时,隐藏该ListView,并显示id是 @android:id/empty 的view,可以用来显示错误信息
当数据是数组或者List时,可以自定义Adapter继承ArrayAdapter,简单些。
ListView性能优化
getView()时花销时间和cpu还有内存的地方主要在 inflater XML文件到构建成Object 和 findViewById()。
用convertView 可以减少 inflater XML文件到构建成Object 的花销
用ViewHolder可以减少 findViewById()的花销
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
// reuse views
if (rowView == null) {
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.rowlayout, null);
// configure view holder
ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) rowView.findViewById(R.id.TextView01);
viewHolder.image = (ImageView) rowView
.findViewById(R.id.ImageView01);
rowView.setTag(viewHolder);
}
// fill data
ViewHolder holder = (ViewHolder) rowView.getTag();
String s = names[position];
holder.text.setText(s);
if (s.startsWith("Windows7") || s.startsWith("iPhone")
|| s.startsWith("Solaris")) {
holder.image.setImageResource(R.drawable.no);
} else {
holder.image.setImageResource(R.drawable.ok);
}
return rowView;
}
Store the selection of a View
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_single_choice, ss));
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, ss));
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
Toast.makeText(this, getListView().getCheckedItemCount(), 1).show();
return true;
}
setChoiceMode()要和对应的layout配合使用。
这里当item被选中时,onOptionsItemSelected()为什么没被调用呢?