View的滑动

一、View的位置参数(都是相对于父容器的位置)

1.View的位置由左上角点、右下角点来确定的。分别对应(左上的X—getLeft,左上的Y—getTop,右下的X—getRight,右下的Y—getBottom)。

2.View的偏移量(translation):表示左上角相对于父容器的偏移量(当前位置与移动后的位置之差叫做偏移量),默认为0。(进过测试只能通过setTranslation改变Translation,补间动画animation.xml无效)通过getTransaltion获取X,Y

3.View的getX(),getY()(都是左上角的点):X = left + translationX;就是左上角的X坐标加上X的偏移量,Y = top + translationY;(就是左上角Y的坐标,加上Y的偏移量)

4.View的getScaleX(),getScaleY():View的内容的左上角的坐标。(向左滑动为正,向右滑动为负)

解释:

二、介绍VelocityTracker、GestureDetector、Scroller

1.VelocityTrancker

作用:速度追踪,用于追踪手指在滑动过程中的速度(包括水平和竖直方向速度)

使用:①、将event事件添加至Velocity对象中   ②、设置时间:指一段时间划过的像素数  ③、获取X,Y方向滑过的像素数(从左向右为正,从上向下为正)

实例:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    private VelocityTracker mVelocityTracker = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //获取Velocity
        mVelocityTracker = VelocityTracker.obtain();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //将事件对象由该对象掌管
        mVelocityTracker.addMovement(event);
        switch (event.getAction()){
            case MotionEvent.ACTION_MOVE:
                //设置时间间隔:速度指的是一段时间内手指划过的像素数
                mVelocityTracker.computeCurrentVelocity(1000);
                //打印速度
                Log.d(TAG,"1秒内滑动X像素数"+mVelocityTracker.getXVelocity()+"  Y像素数"+mVelocityTracker.getYVelocity());
                break;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }
}
MainActivity

注意:当调用getXVelocity()方法的时候,就会返回平均速度。(假设我设置1喵,就是说不是等一秒过后才会,返回getXVelocioty(),而是当你调用getXVelocity()利用数学计算出每秒的速度)。

2.GestureDetector

作用:辅助检测用户的单击、滑动、长按、双击等行为(跟onTouchEvent好想没有区别)

使用:①:实现onGestureDetecotr()接口   ②:创建GestureDetector对象   ③:将onTouchEvent的event事件给detector()对象

实例:(每个接口的方法的作用都写在上面)

//创建GestureDetector
public class GestureTest extends Activity  {
    GestureDetector detector = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //第一步:用匿名类实现接口,供创建GestureDetector时候使用。
        GestureDetector.OnGestureListener gestureListener = new GestureDetector.OnGestureListener() {
            @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) {
                //在屏幕滑动的时候触发
                return false;
            }

            @Override
            public void onLongPress(MotionEvent e) {
                //在屏幕长按的时候触发
            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                //Touch了滑动一点距离后,拿起手时触发。velocityX表示“拖过”动作在横向的速度,velocityY表示“拖过”动作在纵向时的速度
                return false;
            }
        };
        //第二步:构造方法public GestureDetector(Context context,GestureDetector.OnGestureListener listener)
        detector = new GestureDetector(this,gestureListener);

        //解决长按屏幕后无法拖动的现象
        detector.setIsLongpressEnabled(false);

        //监听双击行为
        detector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {
            //严格单击行为。和onSingleTapUp的区别。触发了onSingleTapConfirmed后不能再紧跟另一个单击行为
            @Override
            public boolean onSingleTapConfirmed(MotionEvent e) {
                return false;
            }
            //双击,由两次连续的单击组成,不能和onSingleTapConfirmed共存
            @Override
            public boolean onDoubleTap(MotionEvent e) {
                return false;
            }
            //发生双击行为,双击期间,DOWN、MOVE、UP都会触发此回调
            @Override
            public boolean onDoubleTapEvent(MotionEvent e) {
                return false;
            }
        });
    }

    //第三步:重写Activity的onTouchEvent()方法,并将点击事件给GestureDetector处理
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return detector.onTouchEvent(event);
    }
}
GestureTestActivity

3.Scroller
作用:实现View的弹性滑动

使用:下一节详细讲解View的滑动

三、View的滑动

非弹性滑动

1.使用scrollTo/scrollBy

作用:使View的内容的滑动

使用:①、View自带scrollTo/scrollBy方法 ②、scrollTo/scrollBy区别:scrollTo是相对于父控件位置的滑动。scrollBy是相对于上一scroll位置的滑动

  private Button btn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn = (Button)findViewById(R.id.main_textView);
        btn.scrollTo(30,30);
        btn.scrollBy(50,50);
    }
MainActivity

注:根据源码其实scrollBy(int x,int y)调用scrollTo(int x,int y);(源码分析详见Android开发艺术探索P130)

2.使用动画(AnimationDrawable  除开 属性动画)

详见Drawable类及XMLDrawable的使用  :(只是View视图上的改变,并不改变View的点击位置  但是属性动画可以)

弹性滑动:Scroller来实现有过度效果

第一种:Scroller

1.作用:实现滑动效果。(View内容的滑动)

2.使用流程:创建Scroller对象,之后设定scroller的初始值,并进行重绘,在重绘之前需要重写computeScroll()方法,因为重绘的时候系统会自动调用该方法,在computeScroll()方法中,我们利用computeScrollOffset()方法获取当前应该移动的距离,并用scrollTo()进行移动。

  private Scroller mScroller;
    public TestLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        //创建Scroller
        mScroller = new Scroller(context);
    }

    //滑动到指定位置,参数为滑动的终点
    private void smoothScrollTo(int destX,int destY){
        //获取当前内容的左上角X坐标
        int scrollX = getScrollX();
        Log.d("TestView", scrollX + "-scroll," + destX + "-destX");
        //获取滑动的距离
        int deltaX = scrollX - destX;
        //该方法初始话scroller对象的参数
        mScroller.startScroll(scrollX, 0, deltaX, 0, 1000);
        //重绘,能够调用computeScroll()方法
        invalidate();
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //当按下时调用该方法
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                smoothScrollTo((int)event.getRawX(),0);
                break;
        }
        return super.onTouchEvent(event);
    }

    //当重绘时候调用该方法
    @Override
    public void computeScroll() {
        super.computeScroll();
        //根据时间流逝(重绘需要时间)的百分比计算scrollX和scrollY
        if (mScroller.computeScrollOffset()){
            //获取当前的scrollX和scrollY
            scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
            //执行重绘
            postInvalidate();
        }
    }
TestLinearLayout

第二种:利用Handler来定时移动 (不展开了)

第三种:使用空View改变View的布局  (真正能改变View在layout中的位置)

使用空View改变该View的布局参数
使用:建立空视图(Button1)在View(Button)的左边

在MainActivity中
MarginLayoutParams params = (MarginLayoutParams)mButton1.getLayoutParams();
params.width + = 100;
params.height += 100;
mButton1.setLayoutParams(params);

(这就能够使Button向右移)

原文地址:https://www.cnblogs.com/rookiechen/p/5387980.html