listview 使用技巧,优化学习整理

常用listview 优化技巧

网上有关listview的优化技巧很多,这里就整理两种最基本,也是最常用的优化技巧。listview是采取边滑动边加载的方式,所以如果item数量多,或者控件数量太多,就会造成卡顿的现象,对用户的体验很不好。
首先我们可以通过listview的缓存机制,避免了每次出现新view,调用getview时使用findViewById的方式,因为view实际上是树形结构,如果能减少遍历的次数,肯定会减少卡顿。要这么做需要在adapter中定义一个内部类ViewHolder

public final class ViewHolder{
	public ImageView img;
	public TextView title;
}

这里写了一个imageview和一个textview作为范例
那么在getview中的使用就如下

public View getView(int position,View convertView,ViewGroup parent){
	ViewHolder viewholder;
	//首先判断缓存是否存在,如果不存在就对缓存进行初始化同时给viewholder进行赋值,后面使用holder进行赋值
	if(convertView==null){
	holder =new ViewHolder();
	//使用layoutinflater实例化布局,对convertView进行初始化,并将viewholde初始化后存在convertview中
	convertView =mInflater.inflate(自己的布局文件,null);
	holder.img=(ImageView)convertView.findViewById(自己的ID);
	holder.title=(TextView)convertView.findViewById(自己的ID);
	convertView.setTag(viewholder);//将viewholder存放在convertview中
	}else{//一般来说都是初始化手机屏幕item数量的convertview,之后都是进行复用
	 holder=(ViewGroup)convertView.getTag();
	}
	//完成实例化后进行相关操作,如给图片赋值,写文字之类的操作
	return convertView;
}

ListView的监听

listview的滑动监听是重写listview中的最重要部分,这里总结ListView的两种监听手段,OnTouchListener和OnScrollListener

OnTouchListener

mListView.setOnTouchListener(new View.OnTouchListener(){
	public boolean onTouch(View v, MotionEvent event) {    
		switch (event.getAction()) {        
			case MotionEvent.ACTION_DOWN:
			//触摸时操作            
			break;        
			case MotionEvent.ACTION_UP:
			//移动时操作            
			break;       
 			case MotionEvent.ACTION_MOVE:
 			//离开时操作           
 			break;    
 		}
 	return false;
 	}
 });

举一个常用的例子,就是写可以自动显示,隐藏布局的ListView,经常碰到下拉时候标题栏出现,上划的时候标题栏隐藏,所以就总结一下这个的用法,首先将actionbar隐藏,使用toolbar,这里就不再做具体的介绍
接着需要给ListView增加一个HeaderView,避免第一个item被遮挡

View header = new View(this);
header.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT,(int)getResources().getDimension(R.dimen.abc_action_bar_default_height_meterial)));//设置为系统ActionBar的高度
mListView.addHeaderView(header);

接着就是在监听中写相关的事件了,通过listview在停止状态中的event.getY()就可以获取启示的Y位置,运动状态的event.getY()就是终止位置,两个相减结果如果大于一个值就可以判断移动的方向了,再判断toolbar是该隐藏还是显示。

mTouchSlop=ViewConfiguration.get(this).getScaledTouchSlop();//获取系统认为的最低滑动距离

动画方面的实现就是简单的位移属性动画

//下划时,出现
mAnimatior=ObjectAnimator.ofFloat(mToolbar,"translationY",mToolbar.getTranslationY(),0);
//上滑时,隐藏
mAnimatior=ObjectAnimator.ofFloat(mToolbar,"translationY",mToolbar.getTranslationY(),-mToolbar.getHeight());

这里再对属性动画做一下简单的总结,第一个参数就是要操作的控件,第二个就是定义的属性动画,这里使用的是Y轴平移,getTranslationY()是获取Y轴的偏移值,向上偏移为负,向下偏移为正,第三个参数是起始偏移量,如果只有一个参数,这个参数指结束偏移量,如果后面还有参数,则这个参数是启示,后面参数是结束偏移量。上划时,toolbar.getTranslationY()为0,那么只需让toolBar向上移动toolBar的高度即可,下滑时通过toolbar.getTranslationY()来获取他的向上的偏移量,让他向下移动即可
在这里插入图片描述
这就是getTranslationY为0,所以下滑是最终偏移量为0

OnScrollListener

有两个方法需要重写,onScrollStateChanged和onScroll。

//这里只做简短代码分析,onScrollStateChanged可以获取当前view的状态
public boolean onScrollStateChanged(AbsListView view, int scrollState) {    
  switch (scrollState) {        
   	case OnScrollListener.SCROLL_STATE_IDLE:
   	//滑动停止时            
   	break;        
   	case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
   	//正在滚动时            
   	break;       
    	case OnScrollListener.SCROLL_STATE_FLING: 
    	//手指用力滑动时           
    	break;    
   }
}
//onScroll则是在滚动过程中不断调用的
public void onScroll(AbsListView view,int firstVisbleItem,int visibleItemCount,int totalItemCount){	
	//firstVisbleItem 可见的第一个item
	//visibleItemCount 可见item数量
	//totalItemCount 总共的item数量
	//可以利用这些参数做一些处理,比如判断是否到底:
	//firstVisbleItem+visibleItemCount==totalItemCount&&totalItemCount>0
}

使ListView具有弹性

对控件的拓展是其次的,更重要的是学习到了查看源码,思考解决方案的方式。
View中有个控制滑动到边缘的处理方法

protected boolean overScrollBy(int deltaX, int deltaY,
        int scrollX, int scrollY,
        int scrollRangeX, int scrollRangeY,
        int maxOverScrollX, int maxOverScrollY,
        boolean isTouchEvent)

要做处理的就是maxOverScrollX这个值,源代码对它的注释是沿Y轴扫描过的像素数,源代码中初始值设置的为0,将这个值设置为不为零就可以是listview具有弹性了。
相关源码
为了适配不同的手机尺寸,可以通过获取手机屏幕的密度,根据这个大小设置

    private void initView() {
        DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();//获取屏幕分辨率
        float density = metrics.density;//获取密度
        mMaxOverDistance = (int) (density * mMaxOverDistance);
    }

最后再将mMaxOverDistance赋值给maxOverScrollX即可。

扫描二维码关注公众号,回复: 4938752 查看本文章

实现不同布局的ListView

这种布局在聊天app中经常会遇到,因为两个人聊天的气泡,背景框是不一样的,所以要使用不同的布局,解决办法就是在getView中下手,通过判断item的位置,实例化不同的布局,提供一些关键代码做为总结,重写BaseAdapter中的getItemViewType(),getVIewTypeCount()方法,前者可以根据position判断消息的类型,后者是返回有几种类型(这里就是发送和接受两种类型)

//Message类就是要处理的消息实体对象,含type,text,icon等属性,是一个javabean。
public int getItemViewType(int position) {        
	Message msg = msgList.get(position);//根据位置获取对象        
	return msg.getType(); 返回对象的类型   
}

public int getViewTypeCount() {        
	return 2;    
}
//再在getView中调用getItemViewType根据它的返回值判断是哪种类型,获取不同的布局,
这里就不贴出具体的代码,记得使用ViewHolder加快效率。

猜你喜欢

转载自blog.csdn.net/qq_38594513/article/details/86238272
今日推荐