• [Android UI]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内容的关系:

      小结一下:对于View内容来说,从左往右滑,mScrollX为负;从上往下滑,mScrollY为负。

      那么,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的绘制原理应该有一定理解,这样使用的时候才会得心应手。

  • 相关阅读:
    AdvDataList分页 例码
    问一个关于生成静态页面的问题
    使用XMLDataSource简单实现多级下拉菜单
    简单的封装一个HTML 弹出对话框的空间
    JS 语言强大, 动态修改标准库
    Eclipse IDE 学习
    分布式程序的开发
    Http request Post pk Put
    Forward: X Forwarding with Putty on Windows
    转载: 颠覆了对于design 的认识
  • 原文地址:https://www.cnblogs.com/zhousysu/p/5616307.html
Copyright © 2020-2023  润新知