1.继承ListView,重写overScrollBy方法,调用super.overScrollBy()方法,替换maxOverScrollY参数
优点:简单
缺点:当元素数目较少时,弹动无效
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); } }
2.通过重写onTouchEvent方法,实现弹动效果,解决了元素较少时,不能弹动问题
import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.ListView; public class IpListView extends ListView implements Runnable { private float mLastDownY = 0f; private int mDistance = 0; private int mStep = 10; private boolean mPositive = false; private boolean mIsBounces; public IpListView(Context context, AttributeSet attrs) { super(context, attrs); } public IpListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public IpListView(Context context) { super(context); } @Override public boolean onTouchEvent(MotionEvent event) { if (mIsBounces) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (mLastDownY == 0f && mDistance == 0) { mLastDownY = event.getY(); } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if (mDistance != 0) { mStep = 1; mPositive = mDistance >= 0; this.post(this); return true; } mLastDownY = 0f; mDistance = 0; break; case MotionEvent.ACTION_MOVE: if (mLastDownY != 0f) { mDistance = (int) (mLastDownY - event.getY()); if ((mDistance < 0 && getFirstVisiblePosition() == 0 && getChildAt( 0).getTop() == 0)) { mDistance /= 2; scrollTo(0, mDistance); return true; } else if (mDistance > 0 && getLastVisiblePosition() == getCount() - 1) { final View bottomChildView = getChildAt(getLastVisiblePosition() - getFirstVisiblePosition()); if (getHeight() >= bottomChildView.getBottom()) { mDistance /= 2; scrollTo(0, mDistance); return true; } } } mDistance = 0; break; } } return super.onTouchEvent(event); } @Override public void run() { mDistance += mDistance > 0 ? -mStep : mStep; scrollTo(0, mDistance); if ((mPositive && mDistance <= 0) || (!mPositive && mDistance >= 0)) { scrollTo(0, 0); mDistance = 0; mLastDownY = 0f; return; } mStep += 1; this.postDelayed(this, 10); } public void setBounces(boolean isBounces) { this.mIsBounces = isBounces; } }