当前位置: 58彩票app下载 > 编程技术 > 正文

View的岗位参数及其Scroller类的精通

时间:2019-09-18 11:14来源:编程技术
Anroid 自定义View View的位置参数 正文内容参照他事他说加以考察于《android开辟格局研究》,作为解析总计。 left = getLeft() right = getRight() top = getTop() bottom = getBottom() 1、一些基础 x和y是V

Anroid 自定义View View的位置参数

正文内容参照他事他说加以考察于《android开辟格局研究》,作为解析总计。

  • left = getLeft()
  • right = getRight()
  • top = getTop()
  • bottom = getBottom()

1、一些基础

x和y是View左上角的坐标,translationX和translationY是View左上角针锋相对于容器的偏移量。那多少个参数都以对峙于父容器的坐标。

1.1、掌握View的职位参数

看上边那张图:

图片 1

View的职分参数

那么:

width = right(getRight) - left(getLeft)
height = bottom(getBottom) - top(getTop)

正如在意的是:activity的生命周期中view是在绘制状态,所以getRight、getWidth...这一个主意拿到的是0,具体化解办法可机关钻研。而且那多少个参数都是相对于父容器的。

从Android3.0开头,View扩大了x、y、translationX、translationY。在那之中x和y是View左上角的坐标,translationX和translationY是View左上角针锋相对于父容器的偏移量,暗中认可值为0。那多少个参数也是相对于父容器。那么:

x=left+translationX;
y=top+translationY;

需求当心的是,View平移进度中,top、left表示的是固有左上角的职位音信,其值并不会发出改换,此时发生改换的是x、y、translationX、translationY。

  • x = left + translationX getX()
  • y = top + translationY getY()
1.2、MotionEvent和TouchSlop

getRawX()是周旋于手提式有线电话机荧屏的x坐标,一样的,getRawY()是绝对于手提式有线电话机显示屏的y坐标。

1. MotionEvent

杰出的两种事件类型:

  • ACTION_DOWN--刚接触显示器
  • ACTION_MOVE--显示屏上运动
  • ACTION_UP--显示器上松手的一须臾间

特出的一密密麻麻事件:

  • 点击显示器后离开放手,事件种类:DOWN->UP
  • 点击显示屏滑动一会再放手,事件类别:DOWN->MOVE->...->MOVE->UP

在种类事件中能够通过Motion伊夫nt对象获得点击事件时有发生的x和y坐标。譬喻:

event.getX();
event.getRawX();

那和View的getX是不相同的,再者正是event.getX()获取的是一定于近年来View左上角的x坐标,event.getRawX()再次回到的是争辨于手提式有线电话机显示器左上角的x坐标。

  • ACTION_DOWM:手指刚接触显示屏。
  • ACTION_MOVE:手指在显示屏上运动。
  • ACTION_UP:手指在显示器上松开的一念之差。
2. TouchSlop

TouchSlop是系统所能够分辨出的被感觉是滑动的细小距离,换句话说,当手指在显示器上海好笑剧团动时,如若四回滑动之间的偏离小于那些常量,那么系统就不认为你是在扩充滑动操作。获取那几个常量格局:

ViewConfiguration.get(this).getScaledDoubleTapSlop();

贰个点击事件层出不穷是:DOWN->UP多个滑行事件见惯司空是:DOWN->MOVE->MOVE->...->MOVE->UP

1.3、VelocityTracker、GestureDetector和Scroller

TouchSlop是系统所能识别出的被感觉是滑动的蝇头距离。获取这几个常量:ViewConfiguration.get(getContext.getScaledTouchSlop();

1. VelocityTracker

进程追踪,用于追踪手指在滑行工程中的速度,包罗水平和竖直方向的速度(有正负之分,即速度是有方向的):

private VelocityTracker mVelocityTracker = null;
@Override
public boolean onTouchEvent(MotionEvent event) {
    int index = event.getActionIndex();
    int pointerId = event.getPointerId(index);
    switch (event.getActionMasked()) {
        case MotionEvent.ACTION_DOWN:
            if (mVelocityTracker == null) {
                //获取VelocityTracker对象
                mVelocityTracker = VelocityTracker.obtain();
            } else {
                mVelocityTracker.clear();//清除加入的event
            }
            //加入event
            mVelocityTracker.addMovement(event);
            break;
        case MotionEvent.ACTION_MOVE:
            mVelocityTracker.addMovement(event);
            //1000代表是1s,即单位时间
            mVelocityTracker.computeCurrentVelocity(1000);
            //获取x、y速度
            Loger.e("ACTION_MOVE:" + VelocityTrackerCompat.getXVelocity(mVelocityTracker,
                    pointerId) + "-" + VelocityTrackerCompat.getYVelocity(mVelocityTracker,
                    pointerId));
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            //回收
            mVelocityTracker.recycle();
            break;
    }
    return true;
}

使用较为轻易,不复杂。

咱俩先来看一段套路代码:

2. GestureDetector

手势检查实验,用于支援检查评定客商的单击、滑动、长按、双击等作为。使用较为简单,可参谋官方文档:https://developer.android.com/training/gestures/detector.html
此处说多少个比较常用的:

  • onSingleTapUp,单击
  • onFiling,飞快度滑冰动
  • onScroll,拖动
  • onLongPress,长按
  • onDoubleTap,双击

不过其实支付中,GestureDetector并不是必得用,能够友善在View的OnTouch伊夫nt方法中完结所需的监听。比方监听滑动相关的,建议在onTouch伊夫nt中贯彻,像双击这种能够运用GestureDetector。

 Scroller scroller = new Scroller(getContext; //缓慢滚动到制定位置 private void smoothScrollTo(int destX ,int destY){ int scrollX = getScrollX(); int scrollY = getScrollY(); int deltaX = destX - scrollX; int deltaY = destY - scrollY; scroller.startScroll(scrollX,scrollX,deltaX,deltaY,1000); invalidate(); } @Override public void computeScroll() { if (scroller.computeScrollOffset{ scrollTo(scroller.getCurrX(),scroller.getCurrY; postInvalidate(); } }
3. Scroller

弹性滑动对象,用于落到实处View的弹性滑动。View的scrollTo/scrollBy滑动时刹那间做到,效果不佳。所就要用Scroller来完成有过度效果的滑动。Scroller自身不可能让View弹性滑动,它需求和View的computeScroll方法合营使用手艺共同完毕那几个职能。下边是八个通用模板:

private Scroller mScroller = new Scroller(mContext);
private void scroll(int x, int y) {
    int scrollX = getScrollX();
    int delta = x - scrollX;
    //1000ms的移动
    mScroller.startScroll(scrollX, 0, delta, 0, 1000);
    invalidate();
}
@Override
public void computeScroll() {
    if (mScroller.computeScrollOffset()) {
        scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
        postInvalidate();
    }
}

Scroller类其实是一个在小编中贮存各个活动参数的类,并未关于真正滑动的功能,完成滑动的是scrollTo可以驾驭是在她类的个中举行的滑动设想:你今后以此类中给他三个关于滑动的完美轨迹(从贰个坐标,到另二个坐标和间隔时间),然后scroller依照这一个进展规划(依据时间流逝的比例算出应该滑动到的坐标),在重绘触发的回调函数computeScroll()中再滑动到置顶的岗位scrollTo(scroller.getCurrX(),scroller.getCurrY。总计一下正是,Scroller并不可能实现View的滑动,它必要卓殊View的computeScroll()方法手艺兑现弹性滑动的魔法,它不断让View重绘,而每一回重绘都会形成View举行拓宽小幅滑动,而往往大幅度滑动就结成了弹性滑动,那就是Scroller的规律。

2、View的滑动

相似View的滑行有上边三种办法:通过View自身提供的scrollTo/scrollBy方法,通过动画给View施加平移效果来兑现滑动,通过转移View的LayoutParams使得View重新布局进而达成滑动。

2.1、使用scrollTo/scrollBy

首先要求名曲的是,scrollTo/scrollBy滑动是对view的从头到尾的经过展开活动,而非view本人。比如对于ViewGroup来说,里面包车型地铁零部件都归宿于他的剧情。
下面是scrollTo/scrollBy源码:

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();
        }
    }
}
public void scrollBy(int x, int y) {
    scrollTo(mScrollX + x, mScrollY + y);
}

源码中能够见见scrollBy内部调用的也是scrollTo方法。里面有mScrollX 和mScrollY 参数,那八个参数的情致是view的边和view的剧情的距离。mScrollX 值总是等于view侧面缘和view内容侧面缘在档期的顺序方向的偏离,mScrollY的值总是等于View下面缘和View内容边缘在竖直的相距。那么些值是有正负之分的,举个例子view左侧缘在view内容侧边缘右侧时,那么mScrollX 为正,反之为负。

图片 2

mScrollX /mScrollY

2.2、使用动画片

应用动画片首借使操作View的translationX和translationY属性。能够利用古板View动画,也能够选用属性动画(援救3.0之上,3.0以下接纳开源动画库nineoldandroids:
http://nineoldandroids.com/)
举个例子动用属性动画达成1s内从原来地点向右平移100像素:

ObjectAnimator.ofFloat(mBtn, "translationX", 0, 100)
        .setDuration(1000)
        .start();

提出使用性质动画,动画某些bug,举个例子移动后不可能点击,属性动画未有这些难题。

2.3、改动布局参数

本条就很简短了。例如,一个button要右移,改动LayoutParams里的marginLeft就可以,大概左侧放贰个空的view也可以。

2.4、各样滑动形式相比较
  • scrollTo/scrollBy,内容滑动,容易
  • 卡通,复杂的动画片效果,简单
  • 改动布局参数,复杂

3、弹性滑动

弹性滑动原理是吗一回大的滑动分成若干次小的滑行并在三个光阴内变成。完结方式譬喻:通过Scroller、Handler和postDelayed、Thread和sleep等。

3.1、使用Scroller

第一要细心的是,Scroller的滑行时内容的滑行。在1.3的Scroller介绍中有三个独立使用:

private Scroller mScroller = new Scroller(mContext);
private void scroll(int x, int y) {
    int scrollX = getScrollX();
    int delta = x - scrollX;
    //1000ms的移动
    mScroller.startScroll(scrollX, 0, delta, 0, 1000);
    invalidate();
}
@Override
public void computeScroll() {
    if (mScroller.computeScrollOffset()) {
        scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
        postInvalidate();
    }
}

此间解释下为何能够落实弹性滑动。Scroller调用startSroll最初活动,不过实际上startScroll方法并从未施行活动,只是对数据开展了储存:

图片 3

startScroll

盛传的那多少个参数,startX和startY表示滑动的源点,dx和dy表示的是要滑动的距离,而duration表示是滑动时间。这里的滑动是指View内容的滑动而非View本人地方的更改。再者正是能够滑动的来头是因为:invalidate这一个方法,这些方法调用会招致View重绘,重绘调用view的draw方法,draw方法又会调用computeScroll方法。那时候因为重新了computeScroll方法,方法中又会去向scroller获取当前的scrollX和scrollY,然后通过scrollTo方法完成滑动;接着又调用postInvalidate方法开展下一次重绘;然后又走了上边的流水生产线。invalidate和postInvalidate放的界别在于后面一个是UI线程中调用,前者是非线程中调用。

再来讲下scroller的computeScrollOffset方法。重要看源码的这一部分:

图片 4

computeScrollOffset

本条点子的意思首如果运用时间流逝总计当前的scrollX和scrollY。这样就足以成功弹性滑动。

3.2、通过动画

动画本身就是渐进进程,所以自然弹性效果。举例下边那些代码:

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

以此能够让叁个View在100s内向右移动100像素。
那正是说只要想模仿Scroller来达成View的弹性滑动呢?这里也能够采纳动画的性状来促成:

final int startX = 0;
final int deltaX = 100;
ValueAnimator animator = ValueAnimator.ofInt(0, 1).setDuration(100);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float fraction = animation.getAnimatedFraction();
        mBtn.scrollTo(startX + (int) (deltaX * fraction), 0);
    }
});

事实上您会意识,这么些代码本质上并从未效应于别的对象。这里是依照动画实现的渐变获取View所要滑动的离开。实际上,这里的滑行针对的依旧View的源委而非View自己。

3.3、使用延时国策

延时国策的主干是出殡和埋葬一多级延时音讯,比如Handler、View的postDelayed、线程的sleep方法。Handler主若是透过调用sendEmptyMessageDelayed方法达成,向来如此调用笔者就可以。对于postDelayed方法,能够通过其来发送叁个延时音信,然后再音信中开展View的滑行,如若总是不停地发送这种延时新闻,那么就足以兑现弹性滑动的功效。对于sleep方法来讲,通过在while循环中穿梭地滑动View和sleep。
代码这里就不在贴出,原理和上边三种艺术一样。

骨子里那二种艺术的核情绪想都是把八个安然无事的移动分割成多个一个小的运动,那样的话就须求正视一时间流的工具,举例computeScroll、ValueAnimator、Handler等等。

END

编辑:编程技术 本文来源:View的岗位参数及其Scroller类的精通

关键词: