• Android View学习笔记(二):View滑动方式总结


    一、前言

    在上一篇文章,介绍了View的坐标等基础知识,有了基础知识后,对下面内容的理解也将会容易很多。那么本文介绍的是View滑动的几种方式,这对于View来说,也是需要重要掌握的内容,因为用户无时无刻不在与View打交道,而主要途径有滑动,比如说:界面的切换等。

    二、滑动方式

    在Android中,要滑动一个View有多种方式,下面就来介绍几种常用的方式以及他们的区别。

    1、使用scrollTo或scrollBy

      在View的源码中,提供了专门滑动View的方法,分别是scrollTo和scrollBy。顾名思义,scrollTo是滑动到某一坐标,是绝对滑动;而scrollBy是滑动一段距离,是相对滑动。而需要特别注意的是,这里用的两个方法,都是只改变View的内容的位置,实际上View的坐标并没有改变。为了说明这个问题,我们来看一下源码:

    /**
      * The offset, in pixels, by which the content of this view is scrolled
      * horizontally.
      * {@hide}
      */
        @ViewDebug.ExportedProperty(category = "scrolling")
        protected int mScrollX;
        protected int mScrollY;
    /**
      * Set the scrolled position of your view. This will cause a call to
      * {@link #onScrollChanged(int, int, int, int)} and the view will be
      * invalidated.
      * @param x the x position to scroll to
      * @param y the y position to scroll to
      */
        public void scrollTo(int x, int y) {
            if (mScrollX != x || mScrollY != y) {
                int oldX = mScrollX;
                int oldY = mScrollY;
                mScrollX = x;
                mScrollY = y;
                invalidateParentCaches();
                onScrollChanged(mScrollX, mScrollY, oldX, oldY);
                if (!awakenScrollBars()) {
                    postInvalidateOnAnimation();
                }
            }
        }
    /**
      * Move the scrolled position of your view. This will cause a call to
      * {@link #onScrollChanged(int, int, int, int)} and the view will be
      * invalidated.
      * @param x the amount of pixels to scroll by horizontally
      * @param y the amount of pixels to scroll by vertically
      */
        public void scrollBy(int x, int y) {
            scrollTo(mScrollX + x, mScrollY + y);
        }
    

    实际上scrollBy调用了scrollTo方法,我们只看scrollTo方法,在方法内部,没有涉及到我们上一篇文章说到了View的几个基本参数,而是使用了mScrollX、mScrollY这两个参数,那这两个参数表示的是什么呢?从源码的注释我们可以看出,这两个坐标是表示View内容的偏移量,并且单位是px,即mScrollX是等于View的左边缘和View内容左边缘在水平方向的距离,并且当View内容左边缘在View左边缘的右侧的时候,mScrollX为负,反之为正;同理,mScrollY是等于View的上边缘和View内容上边缘在数值方向的距离,并且Viwe内容上边缘在View上边缘下侧的时候,mScrollY为负,反之为正。为了方便理解,下面用几幅图描述mScrollX、mScrollY和View内容的关系:
    mScrollX和mScrollY与View内容的关系
    小结一下:对于View内容来说,从左往右滑,mScrollX为负;从上往下滑,mScrollY为负。

    可以将视图分为两部分:物理屏幕和View, 将view位置做基准,将屏幕向左移动100(即:-100),view的显示效果是向右移动100
    观察scrollBy方法,以及scrollTo方法,最终对view进行操作滚动,将物理屏幕接收转换来的偏移量,转换成view最终滚动到的坐标,向上滚动时,View的X的坐标是增加的,所以是正值,向下滚动时,View的坐标是减少的,所以是负值

      那么,View和View内容有什么关系呢?可以这样想,对于一个View来说,是一个容器,而View内容是容器里面的东西。对于一个ViewGroup来说,那么它的内容是它的所有子View,那么如果在ViewGroup调用了scrollTo或者scrollBy,它的所有子View会同时移动。对于一个具体的View来说,比如说一个TextView,它的内容就是它里面的文字;对于一个ImageView,它的内容就是它里面的图片,诸如此类。
      这里给出滑动一个View的使用方法:

    TextView textview = (TextView) findViewById(R.id.textview);
    textview.scrollBy(-20,0)      //将textview里面的文字向右滑动20px
    

    总之,使用scrollTo和scrollBy滑动一个View的时候,View的布局参数(比如Top、Left、X、Y等)不会改变,改变的是View的内容位置。

    2、使用属性动画

      使用Android 3.0推出的属性动画,可以很轻松实现一个View的滑动:

    ObjectAnimator.ofFloat(view,"translationX",0,100).setDuration(500).start();
    

    对ofFloat方法的几个参数解释:第一个参数是要滑动的view;第二个参数是对view的某个参数进行改动,这里选择translationX,那么动画效果将作用于view的translationX参数,上一篇文章说到translationX代表view的偏移量,所以属性动画改变的是translationX和translationY值,而不是初始的Top、Left等值;最后两个参数表示前一个参数的起始值和最终值,这里指定为0和100,意思就是说translationX从0变到100。由于涉及到了View的基本参数,所以属性动画这种滑动方式改变的是View本身的位置

    3、改变布局参数

      顾名思义,这个方法是直接对View的位置参数进行改变,即改变LayoutParams,下面给出一个示例再进行分析:

    ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) imageView.getLayoutParams();  //获取imageView的布局参数
    params.leftMargin += 100;     //修改leftMargin的值,相当于xml布局文件中的margin_left的值
    imageView.setLayoutParams(params);  //将新的params值设置进imageView
    

    这里说明一下,对布局参数的改变,实际上是改变了View的top、left、right、bottom这四个初始坐标;然而在上一篇文章有说到,View在绘制完成后这四个初始值是不会改变的,那么是否是矛盾了呢?其实不是的,实际上setLayoutParams()对布局参数的改变,会触发View的重新测绘、布局、绘制这三个流程,那么这四个值也就随之改变了,关于View的三大工作流程,这里不详谈了,以后可能写View机制的源码分析的文章。

    4、使用layout()

      View在绘制的时候会调用layout()来确定View本身的位置,那么我们可以直接调用这个方法来绘制View:

    viwe.layout(int left,int top,int right,int bottom);
    

    一行代码即可调整View的位置了,注意到,以上都是view相对于父容器的坐标,View的位置的确定依赖于这四个坐标,如果这四个坐标不按照view自身的缩放比例设置,会造成View制图的缩放。比如说,一个View的宽和高都是100,选择的位移坐标是(50,50,100,100),那么显然view的宽和高就变成了50,即缩小了。所以如果为了View的正常滑动,一般可以将以上代码修改成如下:

    view.layout(view.getLeft()+offsetX,view.getTop()+offsetY,view.getRight()+offsetX,view.getBottom()+offsetY);
    

    5、使用 offsetLeftAndRight 和 offsetTopAndBottom

      直接调用View的offsetLeftAndRight(int offsetX)或者offsetTopAndBottom(int offsetY)能对view的四个坐标直接进行偏移,以达到移动view的目的。

    imageView.offsetLeftAndRight(50);  //将imageView沿水平正方向偏移50px
    imageView.offsetTopAndBottom(50); //将iamgeView沿竖直正方向偏移50px
    

    原理和onlayout方法差不多,也是导致了view的重新布局、绘制,所以基本参数坐标发生了变化。

    三、总结

    以上介绍了5种常见的view滑动方式,其实还有一种:scroller,这个将会在下一篇文章的弹性滑动中讲述这个类的用法,这里先总结上面说到的5种滑动方式的应用场景:
      ①scrollTo/scrollBy:只适合对view的内容的滑动
      ②属性动画:操作简单,功能强大,能实现复杂的动画效果,不建议用于有交互的View
      ③布局参数、layout、offsetLeftAndRight:适用于交互性强的View,对View的绘制原理应该有一定理解,这样使用的时候才会得心应手。

    作者:丶蓝天白云梦
    链接:https://www.jianshu.com/p/c5261e04d9b7

  • 相关阅读:
    Hibernate课程 初探一对多映射3-1 单向多对一简介
    Hibernate课程 初探一对多映射2-8 set元素属性
    Hibernate课程 初探一对多映射2-7 测试-修改和删除学生信息
    vue.js源码学习分享(二)
    vue.js源码学习分享(一)
    用百度地图做了一个输入地址查询经纬度的小例子
    今天碰到的400错误
    ajax同步
    json键的不能像值一样拼写的问题
    日期格式化
  • 原文地址:https://www.cnblogs.com/sishuiliuyun/p/14578591.html
Copyright © 2020-2023  润新知