美文网首页
View基础概念

View基础概念

作者: 简约黑 | 来源:发表于2016-08-25 14:16 被阅读0次

    View基础概念

    位置参数

    • top、left、right、bottom
      大小均是基于父容器的左或上的距离,由此可计算View自身的宽高
    • translationX、translationY
      Android3.0后新增加的,相对父容器的偏移量,属性动画改变的就是这类的参数

    通过get/set方法调用
    View在平移过程中改变的是偏移量

    MotionEvent相关方法

    • getX、getY
      相对于当前View左上角的x、y坐标

    • getRawX、getRawY
      相对于手机屏幕左上角的x、y坐标

    • ViewConfiguration
      // 获取系统能识别的被认为是滑动的最小距离
      ViewConfiguration.get(getContext()).getScaledTouchSlop();
      // 允许Fling手势动作的最小值
      ViewConfiguration.get(getContext()).getScaledMinimumFlingVelocity();
      // 允许Fling手势动作的最大值
      ViewConfiguration.get(getContext()).getScaledMaximumFlingVelocity();

    • GestureDetector
      手势识别
      GestureDetector mGestureDetector = new GestureDetector(getApplicationContext(), this);
      // 解决长按屏幕无法拖动
      mGestureDetector.setIsLongpressEnabled(false);
      // 触摸屏幕时
      @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) {
      
        }
      
        // 手指快速滑动时,此时也会不断调用onScroll
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            return false;
        }
      

    Activity事件托管给GestureDetector
    @Override
    public boolean onTouchEvent(MotionEvent event) {
    return mGestureDetector.onTouchEvent(event);
    }
    View事件托管给GestureDetector
    mButton.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View arg0, MotionEvent event) {
    return mGestureDetector.onTouchEvent(event);
    }
    });

    • VelocityTracker
      速度追踪
      if(mVelocityTracker == null){
      mVelocityTracker = VelocityTracker.obtain();
      }
      mVelocityTracker.addMovement(event);
      一段时间内手指滑过的像素数,下面是1000毫秒滑动的速度
      // 设置单位
      mVelocityTracker.computeCurrentVelocity(1000);
      // 获取1秒内x方向滑动像素
      int xVelocity = (int) mVelocityTracker.getXVelocity();
      重置和回收的方法
      mVelocityTracker.clear();
      mVelocityTracker.recycle();

    View的滑动

    按正常理解,在屏幕坐标系中,向右滑动为正,向左滑动为左

    • scrollTo/scrollBy
      Scroller滑动方式只能滑动内容
      实际scrollTo/scrollBy滑动时相反
      View左边缘在内容的右边时为正
      View上边缘在内容的下边时为正
      Scroller mScroller = new Scroller(mContext);
      // 开始位置—>终点位置、时间
      mScroller.startScroll(getScrollX(), 0, dx, 0, 500);
      private void smoothScrollTo(int destX, int destY){
      int scrollX = getScrollX();
      int deltaX = destX - scrollX;
      // 滑动的位置-当前位置就是1000ms内滑动的距离
      mScroller.startScroll(scrollX, 0, deltaX, 0, 1000);
      invalidate();
      }
      @Override
      public void computeScroll(){
      if(mScroller.computeScrollOffset()){
      scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
      postInvalidate();
      }
      }

    invalidate方法导致View重绘,draw方法会调用computeScroll方法
    computeScrollOffset方法获取scrollX和scrollY,就是当前应该滑动到的新位置
    通过scrollTo方法来滑动
    整个原理就是插值器通过通过时间流逝百分比计算出当前属性值改变百分比,再通过估值器计算出改变后具体的属性值
    上面的过程就会实现弹性滑动,就是将一次大的滑动分成若干次小的滑动

    • 动画
      ObjectAnimator.ofFloat(view, "translationX", 0, 100).setDuration(100).start();
    • LayoutParams布局参数
      ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams)button.getLayoutParams();
      params.width += 100;
      params.leftMargin += 100;
      // 两种设置方式
      // button.setLayoutParams(params);
      // button.requestLayout();

    View弹性滑动

    • Scroller
      使用Scroller,View普通滑动已经总结了。主要是配合computeScroll方法的使用
    • 动画
      动画本身就具备这样的功能,可以通过ObjectAnimator或ValueAnimator实现
      ValueAnimator animator = ValueAnimator.ofFloat(0, 1).setDuration(200);
      animator.addUpdateListener(new AnimatorUpdateListener(){
      @Override
      public void onAnimationUpdate(ValueAnimator animator){
      // 根据时间流逝得到值的百分比
      int fraction = (int)animator.getAnimatedFraction();
      mButton.scrollTo(startX + deltaX * fraction, 0);
      }
      });

    动画在这里只提供当前值百分比计算,与Scroller类似

    • 延时实现分段滑动
      比如距离100像素,时间1000毫秒,分30次小的滑动,每次滑动延时30毫秒
      private View view;
      private int mCount = 0;
      Handler handler = new Handler(){
      @Override
      public void handleMessage(Message msg) {
      mCount++;
      if(mCount <= 30){
      // 分30次,计算每次移动的位置
      float fraction = mCount/30.0f;
      int scrollX = (int) (fraction * 100);
      view.scrollTo(-scrollX, 0);
      handler.sendEmptyMessageDelayed(0, 30);
      }

            }
        };
      
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            view = findViewById(R.id.text_view);
            handler.sendEmptyMessageDelayed(0, 5000);
        }
      

    这里scrollTo滑动的只是View的内容,不是自身

    相关文章

      网友评论

          本文标题:View基础概念

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