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内容有什么关系呢?可以这样想,对于一个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的绘制原理应该有一定理解,这样使用的时候才会得心应手。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容