Android Scroller类的详细分析
这里采用Scroller实现类似iphone的上下拖拉弹性效果,具体代码如下:
import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; import android.widget.LinearLayout; import android.widget.Scroller; public class BouncyLinearLayout extends LinearLayout { private static final String TAG = "BouncyLinearLayout"; private Scroller mScroller; private GestureDetector mGestureDetector; public BouncyLinearLayout(Context context) { this(context, null); } public BouncyLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); setClickable(true); setLongClickable(true); mScroller = new Scroller(context); mGestureDetector = new GestureDetector(context, new BouncyGestureListener()); } /** * 滚动到目标位置 * @param fx * @param fy */ protected void smoothScrollTo(int fx, int fy) { int dx = fx - mScroller.getFinalX(); int dy = fy - mScroller.getFinalY(); smoothScrollBy(dx, dy); } /** * 设置滚动的相对偏移 * @param dx * @param dy */ protected void smoothScrollBy(int dx, int dy) { //设置mScroller的滚动偏移量 mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy); invalidate();//这里必须调用invalidate()才能保证computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果 } @Override public void computeScroll() { //判断mScroller滚动是否完成 if (mScroller.computeScrollOffset()) { //这里调用View的scrollTo()完成实际的滚动 scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); //必须调用该方法,否则不一定能看到滚动效果 postInvalidate(); } super.computeScroll(); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP : smoothScrollTo(0, 0); break; default: return mGestureDetector.onTouchEvent(event); } return super.onTouchEvent(event); } class BouncyGestureListener implements GestureDetector.OnGestureListener { @Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return true; } @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { int dis = (int)((distanceY-0.5)/2); smoothScrollBy(0, dis); return false; } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub return false; } } }
以上代码只需要稍加改动就可以上下左右4个方向上的弹性效果了
看下面代码,只在BouncyGestureListener的onScroll方法中加了X方向的位移。
import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; import android.widget.LinearLayout; import android.widget.Scroller; public class BouncyLinearLayout extends LinearLayout { private static final String TAG = "BouncyLinearLayout"; private Scroller mScroller; private GestureDetector mGestureDetector; public BouncyLinearLayout(Context context) { this(context, null); } public BouncyLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); setClickable(true); setLongClickable(true); mScroller = new Scroller(context); mGestureDetector = new GestureDetector(context, new BouncyGestureListener()); } /** * 滚动到目标位置 * @param fx * @param fy */ protected void smoothScrollTo(int fx, int fy) { int dx = fx - mScroller.getFinalX(); int dy = fy - mScroller.getFinalY(); smoothScrollBy(dx, dy); } /** * 设置滚动的相对偏移 * @param dx * @param dy */ protected void smoothScrollBy(int dx, int dy) { //设置mScroller的滚动偏移量 mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy); invalidate();//这里必须调用invalidate()才能保证computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果 } @Override public void computeScroll() { //判断mScroller滚动是否完成 if (mScroller.computeScrollOffset()) { //这里调用View的scrollTo()完成实际的滚动 scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); //必须调用该方法,否则不一定能看到滚动效果 postInvalidate(); } super.computeScroll(); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP : smoothScrollTo(0, 0); break; default: return mGestureDetector.onTouchEvent(event); } return super.onTouchEvent(event); } class BouncyGestureListener implements GestureDetector.OnGestureListener { @Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return true; } @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { int disX = (int)((distanceX-0.5)/2); int disY = (int)((distanceY-0.5)/2); smoothScrollBy(disX, disY); return false; } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub return false; } } }
一个iOS风格的边缘弹性效果,支持几乎所有滚动视图
http://www.jcodecraeer.com/a/opensource/2015/1205/3753.html