一、一般我们继承Adapter后 我们都是这么重写getItemId的
@Override
public long getItemId(int position){
return position;
}
如果listview 只是展示没有问题,如果有删除item的话最好f返回该数据的ID
@Override
public long getItemId(int position){
return items.get(position).getId())(;
}
二、有时我们会发现我们修改了item布局的高度却没有生效,是因为getView方法中加载布局的方式问题
使用该加载方式即可
View view = layoutInflater.inflate(R.layout.text_item,parent,false);
三、listview有不同的item需要复写两个方法
int ViewTypeCount = 2;
private interface ViewType{
int TEXT = 0;
int IMAGE = 1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent){
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
if(getItemViewType(position) == ViewType.text){
View view = layoutInflater.inflate(R.layout.text_message_item,parent,false);
...
return view;
}else{
View view = layoutInflater.inflate(R.layout.img_message_item,parent,false);
...
return view;
}
}
@Override
public int getItemViewType(int position){
if(getItem(position) instanceof TextMessage){
return ViewType.TEXT;
}else{
return ViewType.IMAGE;
}
}
@Override
public int getViewTypeCount(){
return ViewTypeCount
}
四、listview 复用机制
ListView的RecycleBin的缓存机制如下图
int ViewTypeCount = 2;
private interface ViewType{
int TEXT = 0;
int IMAGE = 1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent){
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
if(getItemViewType(position) == ViewType.text){
//复用
if(convertView == null){
convertView = layoutInflater.inflate(R.layout.text_message_item,parent,false);
}
...
return convertView;
}else{
if(convertView == null){
convertView = layoutInflater.inflate(R.layout.img_message_item,parent,false);
}
...
return convertView;
}
}
......
五、ViewHold机制 报存findviewbyid,来优化时间
@Override
public View getView(int position, View convertView, ViewGroup parent){
ViewHolder viewHolder;
if(convertView == null){
convertView = layoutInflater.inflate(R.layout.text_message_item,parent,false);
TextView time = convertView.findviewById(R.id.time);
TextView name = convertView.findviewById(R.id.name);
viewHolder = new ViewHolder(time ,name);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder)convertView.getTag()
}
viewHolder.getTime.settext(...)
viewHolder.getName.settext(...)
private static class ViewHolder {
private TextView time;
private TextView name;
public View Holder(Textview time, TextView name){
this.time = time;
this.name = name
}
public TextView getTime(){
return time;
}
public TextView getName(){
return name;
}
}
六、Listview的刷新
1、修改数据源
2、notifyDataSetChanged
七、局部刷新
如果修改的数据源不需要显示在当前listview显示的几个item上就不需要刷新
private void partialRefresh(ListView listview, int position){
if(position >= listView.getFisrtVisiblePosition() && position <= listview.getLastVisiblePosition()){
int childIndex = position - listView.getFirstvisblePosition();
View child = listView.getChildAt(childIndex);
if(child.getTag() instanceof ViewHolder){
((ViewHolder)child.getTag()).refreshContent(datas.get(postion).getContent)}
}
}
ViewHolder.refreshContent方法
baseAdapter中的
private static class ViewHolder {
private TextView time;
private TextView name;
public View Holder(Textview time, TextView name){
this.time = time;
this.name = name
}
public TextView getTime(){
return time;
}
public TextView getName(){
return name;
}
public void refreshContent(String content){
this.name.setText(content)
}
}
八、HeaderView FooterView EmptView
//添加HeaderView
listView.addHeaderView(headerView);
listView.removeHeaderView(headerView);
//添加FooterView
listView.addFooterView(footerView);
listView.removeFooterView(footerView);
//设置EmptyView
listView.setEmptyView(emptyView);
当添加了 HeaderView FooterView 之后 去拿其中一个item就不能用以前的方式了
Object item = data.get(position);//这样取是错的 还可能造成崩溃 数组越界
Object item = adapter.get(position);//这样取是错的
Object item = parent.getItemAtPosition(position);//需要这样取
九、滑动listview的时候取消异步加载例如图片加载
onScrollListener
//ListView 停止滑动
public static int SCROLL_STATE_IDLE= 0;
//手指还停留在屏幕上,ListView随着手指的滑动而滑动
public static int SCROLL_STATE_TOUCH_SCROLL =1;
//手指已经离开屏幕,ListView还在随着惯性滑动
public static int SCROLL_STATE_FLING = 2;
public interface OnScrollListener{
public void onScrollStateChanged(AbsListView view, int ScrollState);
public void onScroll(AbsListView view, int firstVisibleItem,int totalItemCount)
}
十、分批加载onScrollListener中的onScroll
listView.setOnScrollListener(new AbsListView.OnScrollListener()){
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount){
if(firstVisibleItem + visibleItemCount == totalItemCount){//监测滑动到底部了
Toast.makeText(MainActivity.this,"自动加载新数据",Toast.LENGTH_SHORT).show();
int count = data.size();
for (int i = count; i< count +100; i++){//给数据中再添加数据
data.add(new Message("我是文本消息"+i))
}
adapter.notifyDataSetChanged();//更新界面
}
}
}
十一、listView的setSelection方法
public void setSelection(int position)
如图点击可以跳转到上次看的位置
public void setSelectionFromTop(int position ,int y)//设置item距离顶部还有多少距离,适合当上次滑动到某个位置,下次进入还从该位置查看
十二、Listview的常用属性
滑动后右侧滑动条是否消失
android:fadeScrollbars=“true”
滑动后左侧滑动条可以手动拖拉
android:fastScrollEnabled=“true”
右侧滑动条一直显示
android:fastScrollAlwayVisible=“true”
overScrollMode设置为always时候当listview滑动到顶部之后还可以往下拉,never 则不会 ,ifContentScrolls字面意思如果内容需要滚动的时候可以往下拉
android:overScrollMode=“always”
设置顶部可下拉的背景颜色
android:overScrollHeader="@android:color/light"
设置底部可上拉的底部背景颜色
android:overScrollFooter="@android:color/light"
设置顶部和底部边缘渐变效果
android:requiresFadingEdge=“vertical”
android:fadingEdgeLength=“100dp”
android:cacheColorHint="@android:color/light"
android:scrollingCache=“false”
item点击与没有点击的效果
android:listSelector="@drawable/list_view_selector"
item间的分割线也可以设置自己需要的
android:divider="@null"
android:dividerHeight=“3px”
android:headerDividerEnabled= “true”//第一个分割线不显示
android:footerDividerEnabled= “true”//最后一个分割线不显示
listView从底部开始布局 item数量少的时候 上面是空的
android:stackFromBottom=“true”
增加消息的时候总会显示最底部的消息,跟微信来新消息一样
android:transcriptMode=“alwaysScroll”