Scroller(四)——实现拉动后回弹的布局
PS:
该篇博客已经deprecated,不再维护,详情请参见
站在源码的肩膀上全解Scroller工作机制
http://blog.csdn.NET/lfdfhl/article/details/53143114
MainActivity如下:
- package cc.testscroller2;
- import android.os.Bundle;
- import android.app.Activity;
- public class MainActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- }
- }
BounceableLinearLayout如下:
- package cc.testscroller2;
- import android.content.Context;
- import android.util.AttributeSet;
- import android.view.GestureDetector;
- import android.view.MotionEvent;
- import android.widget.LinearLayout;
- import android.widget.Scroller;
- /**
- * 总体思路:
- * 处理View的Touch事件,即重写onTouchEvent()方法:
- * 当手指抬起时将其回到原点,其余情况交给GestureDetector处理.
- *
- * 在GestureDetector中重点是覆写onScroll()方法.在该方法中得到
- * Y方向滑动的距离,从而设置 mScroller.startScroll()方法,准备滑动.
- * 随之刷新界面invalidate()从而执行方法computeScroll().
- * 在computeScroll()方法中调用 scrollTo()方法实现真正的滑动.
- *
- * 注意事项:
- * 1 scrollTo()方法的参数:
- * scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
- * 并且在此之后也要调用postInvalidate()进行刷新
- *
- *
- * 方法说明:
- * 1 mScroller.getFinalX(Y)()
- * The final X(Y) offset as an absolute distance from the origin.
- * 返回滚动结束位置(得到当前X(Y)距离原始位置的值).仅针对"fling"滚动有效.
- * 也就是说该方法是针对滚动结束而言的.
- *
- * 坐标方向:
- * X方向的距离,正数向左,负数向右
- * Y方向的距离,正数向上,负数向下
- *
- * 2 mScroller.getCurrX(Y)()
- * The new X offset as an absolute distance from the origin.
- * The new Y offset as an absolute distance from the origin.
- * 返回当前滚动 X(Y)方向的偏移
- * 也就是说该方法是针对滚动中而言的.
- *
- * 坐标方向:
- * X方向的距离,正数向左,负数向右
- * Y方向的距离,正数向上,负数向下
- *
- *
- * 3 startScroll(int startX, int startY, int dx, int dy, int duration)
- * 第一,二个参数起始位置;第三,四个滚动的偏移量;第五个参数持续时间
- *
- *
- */
- public class BounceableLinearLayout extends LinearLayout {
- private Scroller mScroller;
- private GestureDetector mGestureDetector;
- public BounceableLinearLayout(Context context) {
- this(context, null);
- }
- public BounceableLinearLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- setClickable(true);
- setLongClickable(true);
- mScroller = new Scroller(context);
- mGestureDetector = new GestureDetector(context, new GestureListenerImpl());
- }
- @Override
- public void computeScroll() {
- if (mScroller.computeScrollOffset()) {
- System.out.println("computeScroll()---> "+
- "mScroller.getCurrX()="+mScroller.getCurrX()+","+
- "mScroller.getCurrY()="+mScroller.getCurrY());
- scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
- //必须执行postInvalidate()从而调用computeScroll()
- //其实,在此调用invalidate();亦可
- postInvalidate();
- }
- super.computeScroll();
- }
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_UP :
- //手指抬起时回到最初位置
- prepareScroll(0, 0);
- break;
- default:
- //其余情况交给GestureDetector手势处理
- return mGestureDetector.onTouchEvent(event);
- }
- return super.onTouchEvent(event);
- }
- class GestureListenerImpl implements GestureDetector.OnGestureListener {
- @Override
- public boolean onDown(MotionEvent e) {
- return true;
- }
- @Override
- public void onShowPress(MotionEvent e) {
- }
- @Override
- public boolean onSingleTapUp(MotionEvent e) {
- return false;
- }
- //控制拉动幅度:
- //int disY=(int)((distanceY - 0.5)/2);
- //亦可直接调用:
- //smoothScrollBy(0, (int)distanceY);
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {
- int disY = (int) ((distanceY - 0.5) / 2);
- beginScroll(0, disY);
- return false;
- }
- public void onLongPress(MotionEvent e) {
- }
- @Override
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {
- return false;
- }
- }
- //滚动到目标位置
- protected void prepareScroll(int fx, int fy) {
- int dx = fx - mScroller.getFinalX();
- int dy = fy - mScroller.getFinalY();
- beginScroll(dx, dy);
- }
- //设置滚动的相对偏移
- protected void beginScroll(int dx, int dy) {
- System.out.println("smoothScrollBy()---> dx="+dx+",dy="+dy);
- //第一,二个参数起始位置;第三,四个滚动的偏移量
- mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy);
- System.out.println("smoothScrollBy()---> " +
- "mScroller.getFinalX()="+mScroller.getFinalX()+","+
- "mScroller.getFinalY()="+mScroller.getFinalY());
- //必须执行invalidate()从而调用computeScroll()
- invalidate();
- }
- }
main.xml如下:
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <cc.testscroller2.BounceableLinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="向下拉动后松开"
- />
- </cc.testscroller2.BounceableLinearLayout>
- </RelativeLayout>

浙公网安备 33010602011771号