一.ListView常规使用
1.list item布局文件
2.Adapter
public class MyAdapter extends BaseAdapter {
private List mData;
private LayoutInflater mInflater;
public MyAdapter(Context context, List mData) {
this.mData = mData;
mInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Object 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 viewHolder = new ViewHolder();
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item, null);
viewHolder.imageView = (ImageView) convertView.findViewById(R.id.listview_image);
viewHolder.textView = (TextView)convertView.findViewById(R.id.listview_text);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.imageView.setImageResource(R.mipmap.ic_launcher);
viewHolder.textView.setText(mData.get(position).toString());
return convertView;
}
private final class ViewHolder {
ImageView imageView;
TextView textView;
}
}
3.Activity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
for(int i = 0; i < 20; i++) {
list.add(Integer.valueOf(i));
}
listView = (ListView) findViewById(R.id.list_view);
myAdapter = new MyAdapter(this, list);
listView.setAdapter(myAdapter);
}
4.Layout
5.效果图:
优化方式:
1.重用convertView:通过重用convertView来减少不必要的view的创建,另外Inflate操作会把xml文件实例化成相应的View实例,是耗时操作。复用convertView的时候,当图片加载采用异步的方式加载的时候可能出现错位的情况,解决办法是给给 ImageView 设置一个 tag, 并预设一个图片。点击打开链接
实际上跟多图片加载框架比如Glide加载图片都是异步的,提高性能。
2.减少findViewById()操作:将xml文件中的元素封装成viewHolder静态类,通过convertView的setTag和getTag将view和相应的对象绑定在一起,避免不必要的findViewById操作。
3.避免在getView方法中作耗时操作:例如加载本地Image需要载入内存以及解析Bitmap,都是比较耗时的操作,如果用户快速滑动listView,会因为getView逻辑过于复杂而造成滑动卡顿的现象。用户滑动的时候不要加载图片,待滑动完成再加载,可以使用第三方的库glide。
4.Item的布局层次结构尽量简单,避免布局太深或者不必要的重绘。
5.尽量保证Adapter的hasStablelds()返回true,这样在notifyDataSetChaged()的时候,如果Item内容没有变化,listView将不会重绘这个View,达到优化的目的。
6.在一些场景中,ScrollView内会包含多个ListView,可以把listView的高度写死固定下来。由于ScrollView在快速下滑过程中需要大量计算每个listView的高度,阻塞UI线程导致卡顿现象,如果每一个item的高度是均匀的,可以通过计算把listView的高度确定下来。
7.使用RecyclerView代替ListView:RecyclerView的用法
每个item内容的变动,ListView都需要调用notifyDataSetChanged来更新全部item。Recycler可以实现当前item的局部刷新,并且引入了增加和移除的动态效果,在性能和定制上有很大改善。
8.开启硬件加速。
二.ListView的扩展
1.设置列别分隔线
android:divider="@color/colorPrimary"
android:dividerHeight="10dp"
android:scrollbars="none"
3.改变item点击效果
android:listSelector="@android:color/transparent"
4.设置ListView需要显示在第几项
listView.setSelection(N);
或者
listView.smoothScrollToPosition(N);
5.动态改变ListView
mData.add("string");
mAdapter.notifyDataSetChanded();
6.遍历ListView
for (int i = 0; i < listView.getCount(); i++) {
View view = listView.getChildAt(i);
}
7.ListView滑动监听
OnTouchListener
listView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//
break;
case MotionEvent.ACTION_HOVER_MOVE:
//
break;
case MotionEvent.ACTION_UP:
//
break;
}
return false;
}
});
OnScrollListener
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
//
break;
case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
//
break;
case AbsListView.OnScrollListener.SCROLL_STATE_FLING:
//
break;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0) {
//滚动到最后一行
}
int lastVisibleItemPosition = 0;
if (firstVisibleItem > lastVisibleItemPosition) {
//上滑
} else if (firstVisibleItem < lastVisibleItemPosition) {
//下滑
}
lastVisibleItemPosition = firstVisibleItem;
}
});
//获取可见区域最后一个可见item id
listView.getLastVisiblePosition();
//获取可见区域第一个可见item id
listView.getFirstVisiblePosition();
8.具有弹性的ListView
重写LisyView的overScrollBy()方法
@Override
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, initHeight(100), isTouchEvent);
}
private int initHeight(int height) {
float density = mContext.getResources().getDisplayMetrics().density;
return (int) (height * density);
}
9.设置不同的item,Adapter中的type方法
@Override
public int getViewTypeCount() {
return super.getViewTypeCount();
}