Android开发艺术探索笔记 ——View(一)

作者: soberbad | 来源:发表于2016-08-01 16:57 被阅读455次

    Android开发艺术探索笔记 ——View(一)

    View的基础知识

    什么是View

    View是Android中所有控件的基类。是一种界面层控件的抽象

    View的位置参数

    Paste_Image.png Paste_Image.png
    参数名 获取方式 含义
    top getTop() View左上角纵坐标
    left getLeft() View左上角横坐标
    bottom getBottom() View右下角纵坐标
    right getRight() View右下角横坐标
    View:x/y getX()/getY() View左上角坐标
    translationX getTranslationX() View左上角相对于父容器的偏移量
    translationY getTranslationY() View左上角相对于父容器的偏移量
    MotionEvent:x/y event.getX()/event.getY() 点击事件相对于View左上角的坐标
    MotionEvent:rawX/rawY event.getRawX()/event.getRawY() 点击事件相对于手机屏幕左上角的坐标

    MotionEvent

    • ACTION_DOWN
    • ACTION_MOVE
    • ACTION_UP

    MotionEvent获取点击事件x,y坐标:

    getX/getY 相对于View左上角
    getRawX/getRawY 相对于手机屏幕左上角

      //在View或Activity中拦截touch events,重写onTouchEvent方法
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            int action = MotionEventCompat.getActionMasked(event);
            switch (action) {
                case (MotionEvent.ACTION_DOWN):
                    Log.d(TAG,"action down");
                    return true;
                case (MotionEvent.ACTION_MOVE):
                    Log.d(TAG,"action move");
                    return true;
                case (MotionEvent.ACTION_UP):
                    Log.d(TAG,"action up");
                    return true;
                case (MotionEvent.ACTION_CANCEL):
                    Log.d(TAG,"action cancel");
                    return true;
                case (MotionEvent.ACTION_OUTSIDE):
                    Log.d(TAG,"action outside");
                    return true;
                default:
                    return super.onTouchEvent(event);
            }
        }
        //对于View,可以使用setOnTouchListener()方法来监听touch events而不需要继承现有的View
        View myView = findViewById(R.id.my_view);
    myView.setOnTouchListener(new OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            // ... Respond to touch events
            return true;
        }
    });
    

    TouchSlop

    滑动的最小距离,常量,和设备有关。

    //获取方式:
    ViewConfiguration.get(getContext()).getScaledTouchSlop();
    

    VelocityTracker

    学习资料:
    1.https://developer.android.com/training/gestures/movement.html

    追踪手指滑动的速度

    使用过程:

      //在View的onTouchEvent方法中
      VelocityTracker velocityTracker = VelocityTracker.obtain();
      velocityTracker.addMoveMent(event);
      
      //时间间隔设为1000ms
      tracker.computeCurrentVelocity(1000);
      int Vx = (int)velocityTracker.getXVelocity();
      int Vy = (int)VelocityTracker.getYVelocity();
      
      //不再使用的时候,需要清除并回收
      velocityTracker.clear();
      velocityTracker.recycle();
    

    GestureDetector

    手势监测:单击,滑动,长按,双击等等。

    使用方法:

    • 1.实例化GestureDetectorCompat
    • 2.如需监测所有的手势,则实现GestureDetector.OnGestureListener接口和GestureDetector.OnDoubleTapListener接口。
    • 3.若只需监测部分手势,则继承GestureDetector.SimpleOnGestureListener类。
    
    //监测所有的手势
    public class MainActivity extends Activity implements
            GestureDetector.OnGestureListener,
            GestureDetector.OnDoubleTapListener{
    
        private static final String DEBUG_TAG = "Gestures";
        private GestureDetectorCompat mDetector;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //实例化GestureDetectorCompat
            mDetector = new GestureDetectorCompat(this,this);
            //将双击事件交给GestureDetectorCompat监听
            mDetector.setOnDoubleTapListener(this);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event){
            this.mDetector.onTouchEvent(event);
            return super.onTouchEvent(event);
        }
    
        @Override
        public boolean onDown(MotionEvent event) {
            Log.d(DEBUG_TAG,"onDown: " + event.toString());
            return true;
        }
    
        @Override
        public boolean onFling(MotionEvent event1, MotionEvent event2,
                float velocityX, float velocityY) {
            Log.d(DEBUG_TAG, "onFling: " + event1.toString()+event2.toString());
            return true;
        }
    
        @Override
        public void onLongPress(MotionEvent event) {
            Log.d(DEBUG_TAG, "onLongPress: " + event.toString());
        }
    
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
                float distanceY) {
            Log.d(DEBUG_TAG, "onScroll: " + e1.toString()+e2.toString());
            return true;
        }
    
        @Override
        public void onShowPress(MotionEvent event) {
            Log.d(DEBUG_TAG, "onShowPress: " + event.toString());
        }
    
        @Override
        public boolean onSingleTapUp(MotionEvent event) {
            Log.d(DEBUG_TAG, "onSingleTapUp: " + event.toString());
            return true;
        }
    
        @Override
        public boolean onDoubleTap(MotionEvent event) {
            Log.d(DEBUG_TAG, "onDoubleTap: " + event.toString());
            return true;
        }
    
        @Override
        public boolean onDoubleTapEvent(MotionEvent event) {
            Log.d(DEBUG_TAG, "onDoubleTapEvent: " + event.toString());
            return true;
        }
    
        @Override
        public boolean onSingleTapConfirmed(MotionEvent event) {
            Log.d(DEBUG_TAG, "onSingleTapConfirmed: " + event.toString());
            return true;
        }
    }
    
    
    
    //监测部分手势
    public class MainActivity extends Activity {
    
        private GestureDetectorCompat mDetector;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mDetector = new GestureDetectorCompat(this, new MyGestureListener());
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event){
            this.mDetector.onTouchEvent(event);
            return super.onTouchEvent(event);
        }
    
        class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
            private static final String DEBUG_TAG = "Gestures";
    
            @Override
            public boolean onDown(MotionEvent event) {
                Log.d(DEBUG_TAG,"onDown: " + event.toString());
                return true;
            }
    
            @Override
            public boolean onFling(MotionEvent event1, MotionEvent event2,
                    float velocityX, float velocityY) {
                Log.d(DEBUG_TAG, "onFling: " + event1.toString()+event2.toString());
                return true;
            }
        }
    }
    
    

    Scroller

    弹性滑动对象,用于实现View的弹性滑动。

    学习资料:
    1.Android Scroller完全解析,关于Scroller你所需知道的一切
    2.Animating a Scroll Gesture

    Scroller的基本用法:

    • 1.创建Scroller实例
    • 2.调用startScroll()方法来初始化
    • 3.重写View的computeScroll()方法,并在其内部完成平滑移动的逻辑。

    View的滑动

    三种方式实现View的滑动:

    • 1.View的ScrollToScrollBy方法。
    • 2.动画
    • 3.改变View的LayoutParams使View重新布局从而实现滑动

    使用ScrollTo和ScrollBy

    • ScrollTo相对于初始位置滚动某段距离。
    • ScrollBy相对于当前位置滚动某段距离。
    • 其中,水平方向,正值为向左滚动,负值为向右滚动。竖直方向,正值为向上滚动,负值为向下滚动。
    • 两个Scroll方法的滚动都是跳跃式的,没有平滑移动的效果。

    使用动画

    使用动画操作View的translationXtranslationY两个属性来移动View。可使用属性动画/View动画。

    View动画是对View的影像进行操作的。也就是说View动画并不能真正的改变View的位置。
    属性动画是真正改变View的位置,但它是从Android3.0开始推出的。

    //View动画实现移动
    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:fillAfter="true"
        >
       <translate
           android:fromXDelta="0"
           android:fromYDelta="0"
           android:toXDelta="500"
           android:toYDelta="1000"
           android:duration="10000"
           android:interpolator="@android:anim/linear_interpolator"
           />
    </set>
    
     Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate);
            layout.setAnimation(animation);
            animation.start();
    
    //使用属性动画实现移动
    ObjectAnimator.ofFloat(layout,"translationX",0,100).setDuration(1000).start();
    

    改变布局参数

    改变布局参数LayoutParams

     ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) layout.getLayoutParams();
                    params.width+=1000;
                    params.leftMargin+=1000;
                    layout.requestLayout();
    

    三种滑动方式的对比

    方式 优点 缺点
    scrollTo/scrollBy 原生方法,操作简单,适用于对内容的滑动 不能滑动View本身
    动画 操作简单,适用于没有交互的View和复杂的动画效果 Android3.0以下的兼容问题
    改变布局参数 适用于有交互的View 操作较复杂

    弹性滑动

    将一次时间长的滑动分成若干次短的滑动。

    使用Scroller

    //1.创建Scroller
    Scroller scroller = new Scroller(context);
    ...
    
    //2.调用Scroller的startScroll方法
    int scrollX = getScrollX();
    int deltaX = destX - scrollX;
    scroller.startScroll(scrollX,0,deltaX,0,1000);
    invalidate();
    
    //3.复写computeScroll()方法
    @Override
    public void computeScroll(){
        if(scroller.computeScrollOffset()){
           scrollTo(scroller.getCurrX(),scroller.getCurrY());
           invalidate();
        }
    }
    

    相关文章

      网友评论

        本文标题:Android开发艺术探索笔记 ——View(一)

        本文链接:https://www.haomeiwen.com/subject/rzaxsttx.html