Android 实现ListView的弹性效果

转载了一片文章  不过之前自己试的时候 第一种方法虽然能实现上下弹性回滚 但是偶尔会卡住不回滚 还是有一些bug 第二种还没有试 先记录下吧 暂时还没有好的弹性回滚


关于在Android中实现ListView的弹性效果,有很多不同的方法,网上一搜,也有很多,下面贴出在项目中经常用到的两种实现ListView弹性效果的方法(基本上拿来就可以用),供大家参考:

     第一种比较简单,好容易理解,只是动态改变了ListView在Y轴上的可移动距离,代码如下:

  1. import android.content.Context;  
  2. import android.util.AttributeSet;  
  3. import android.util.DisplayMetrics;  
  4. import android.widget.ListView;  
  5. /** 
  6.  * 弹性ListView。 
  7.  * @author E 
  8.  */  
  9. public class FlexiListView extends ListView{  
  10.     //初始可拉动Y轴方向距离  
  11.     private static final int MAX_Y_OVERSCROLL_DISTANCE = 100;  
  12.     //上下文环境  
  13.     private Context mContext;  
  14.     //实际可上下拉动Y轴上的距离  
  15.     private int mMaxYOverscrollDistance;  
  16.       
  17.     public FlexiListView(Context context){  
  18.         super(context);  
  19.         mContext = context;  
  20.         initBounceListView();  
  21.     }  
  22.       
  23.     public FlexiListView(Context context, AttributeSet attrs) {  
  24.         super(context, attrs);  
  25.         mContext = context;  
  26.         initBounceListView();  
  27.     }  
  28.       
  29.     public FlexiListView(Context context, AttributeSet attrs, int defStyle) {  
  30.         super(context, attrs, defStyle);  
  31.         mContext = context;  
  32.         initBounceListView();  
  33.     }  
  34.       
  35.     private void initBounceListView(){  
  36.         final DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();  
  37.             final float density = metrics.density;  
  38.         mMaxYOverscrollDistance = (int) (density * MAX_Y_OVERSCROLL_DISTANCE);  
  39.     }  
  40.       
  41.     @Override  
  42.     protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX,   
  43.             int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {   
  44.         //实现的本质就是在这里动态改变了maxOverScrollY的值  
  45.         return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, mMaxYOverscrollDistance, isTouchEvent);    
  46.     }  
  47.       
  48. }  
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.widget.ListView;
/**
 * 弹性ListView。
 * @author E
 */
public class FlexiListView extends ListView{
	//初始可拉动Y轴方向距离
    private static final int MAX_Y_OVERSCROLL_DISTANCE = 100;
    //上下文环境
    private Context mContext;
    //实际可上下拉动Y轴上的距离
	private int mMaxYOverscrollDistance;
	
	public FlexiListView(Context context){
		super(context);
		mContext = context;
		initBounceListView();
	}
	
	public FlexiListView(Context context, AttributeSet attrs) {
		super(context, attrs);
		mContext = context;
		initBounceListView();
	}
	
	public FlexiListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		mContext = context;
		initBounceListView();
	}
	
	private void initBounceListView(){
		final DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
        	final float density = metrics.density;
		mMaxYOverscrollDistance = (int) (density * MAX_Y_OVERSCROLL_DISTANCE);
	}
	
	@Override
	protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, 
			int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { 
		//实现的本质就是在这里动态改变了maxOverScrollY的值
		return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, mMaxYOverscrollDistance, isTouchEvent);  
	}
	
}

     第二种方法,结合了手势来实现ListView的弹性效果,这里可以根据手势来进行更多的扩展,代码如下:

  1. import android.content.Context;  
  2. import android.graphics.Rect;  
  3. import android.util.AttributeSet;  
  4. import android.view.GestureDetector;  
  5. import android.view.GestureDetector.OnGestureListener;  
  6. import android.view.MotionEvent;  
  7. import android.view.View;  
  8. import android.view.animation.TranslateAnimation;  
  9. import android.widget.ListView;  
  10. /** 
  11.  * 具有弹性效果的ListView。主要是实现父类dispatchTouchEvent方法和OnGestureListener中onScroll方法。 
  12.  * @author E 
  13.  */  
  14. public class FlexibleListView extends ListView implements OnGestureListener{  
  15.       
  16.     private Context context = null;  
  17.     private boolean outBound = false;  
  18.     private int distance;  
  19.     private int firstOut;  
  20.       
  21.     public FlexibleListView(Context context, AttributeSet attrs) {  
  22.         super(context, attrs);  
  23.         this.context = context;  
  24.     }  
  25.       
  26.     public FlexibleListView(Context context, AttributeSet attrs, int defStyle) {  
  27.         super(context, attrs, defStyle);  
  28.         this.context = context;  
  29.     }  
  30.       
  31.     public FlexibleListView(Context context) {  
  32.         super(context);  
  33.         this.context = context;  
  34.     }  
  35.       
  36.     GestureDetector lisGestureDetector = new GestureDetector(context, this);  
  37.       
  38.     @Override  
  39.     public boolean dispatchTouchEvent(MotionEvent event) {  
  40.         int act = event.getAction();  
  41.         if ((act == MotionEvent.ACTION_UP || act == MotionEvent.ACTION_CANCEL)  
  42.         && outBound) {  
  43.         outBound = false;  
  44.         // scroll back  
  45.         }  
  46.         if (!lisGestureDetector.onTouchEvent(event)) {  
  47.             outBound = false;  
  48.         } else {  
  49.             outBound = true;  
  50.         }  
  51.         Rect rect = new Rect();    
  52.         getLocalVisibleRect(rect);    
  53.         TranslateAnimation am = new TranslateAnimation( 00, -rect.top, 0);    
  54.         am.setDuration(300);    
  55.         startAnimation(am);    
  56.         scrollTo(00);  
  57.         return super.dispatchTouchEvent(event);  
  58.     }  
  59.   
  60.     @Override  
  61.     public boolean onDown(MotionEvent e) {  
  62.         return false;  
  63.     }  
  64.   
  65.     @Override  
  66.     public void onShowPress(MotionEvent e) {  
  67.     }  
  68.   
  69.     @Override  
  70.     public boolean onSingleTapUp(MotionEvent e) {  
  71.         return false;  
  72.     }  
  73.   
  74.     @Override  
  75.     public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,  
  76.             float distanceY) {  
  77.         int firstPos = getFirstVisiblePosition();  
  78.         int lastPos = getLastVisiblePosition();  
  79.         int itemCount = getCount();  
  80.         // outbound Top  
  81.         if (outBound && firstPos != 0 && lastPos != (itemCount - 1)) {  
  82.         scrollTo(00);  
  83.         return false;  
  84.         }  
  85.         View firstView = getChildAt(firstPos);  
  86.         if (!outBound)  
  87.         firstOut = (int) e2.getRawY();  
  88.         if (firstView != null&& (outBound || (firstPos == 0  
  89.            && firstView.getTop() == 0 && distanceY < 0))) {  
  90.         // Record the length of each slide  
  91.         distance = firstOut - (int) e2.getRawY();  
  92.         scrollTo(0, distance / 2);  
  93.         return true;  
  94.         }  
  95.         // outbound Bottom  
  96.         return false;  
  97.     }  
  98.   
  99.     @Override  
  100.     public void onLongPress(MotionEvent e) {  
  101.     }  
  102.   
  103.     @Override  
  104.     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,  
  105.             float velocityY) {  
  106.         return false;  
  107.     }  
  108. }  
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.widget.ListView;
/**
 * 具有弹性效果的ListView。主要是实现父类dispatchTouchEvent方法和OnGestureListener中onScroll方法。
 * @author E
 */
public class FlexibleListView extends ListView implements OnGestureListener{
	
	private Context context = null;
	private boolean outBound = false;
	private int distance;
	private int firstOut;
	
	public FlexibleListView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
	}
	
	public FlexibleListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		this.context = context;
	}
	
	public FlexibleListView(Context context) {
		super(context);
		this.context = context;
	}
	
	GestureDetector lisGestureDetector = new GestureDetector(context, this);
	
	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		int act = event.getAction();
		if ((act == MotionEvent.ACTION_UP || act == MotionEvent.ACTION_CANCEL)
		&& outBound) {
		outBound = false;
		// scroll back
		}
		if (!lisGestureDetector.onTouchEvent(event)) {
			outBound = false;
		} else {
			outBound = true;
		}
		Rect rect = new Rect();  
        getLocalVisibleRect(rect);  
        TranslateAnimation am = new TranslateAnimation( 0, 0, -rect.top, 0);  
        am.setDuration(300);  
        startAnimation(am);  
        scrollTo(0, 0);
		return super.dispatchTouchEvent(event);
	}

	@Override
	public boolean onDown(MotionEvent e) {
		return false;
	}

	@Override
	public void onShowPress(MotionEvent e) {
	}

	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		return false;
	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		int firstPos = getFirstVisiblePosition();
		int lastPos = getLastVisiblePosition();
		int itemCount = getCount();
		// outbound Top
		if (outBound && firstPos != 0 && lastPos != (itemCount - 1)) {
		scrollTo(0, 0);
		return false;
		}
		View firstView = getChildAt(firstPos);
		if (!outBound)
		firstOut = (int) e2.getRawY();
		if (firstView != null&& (outBound || (firstPos == 0
		   && firstView.getTop() == 0 && distanceY < 0))) {
		// Record the length of each slide
		distance = firstOut - (int) e2.getRawY();
		scrollTo(0, distance / 2);
		return true;
		}
		// outbound Bottom
		return false;
	}

	@Override
	public void onLongPress(MotionEvent e) {
	}

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		return false;
	}
}


     以上两种常用的实现方法,整理出来,希望对大家有所帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值