您的位置:首页 > 运维架构

View的位置参数mLeft,mRight,mTop,mBottom,mScrollX,mScrollY,x,y,translationX,translationY

2016-11-22 17:35 253 查看
前面有分析过程View的measure,layout,draw三个过程:

Android应用程序窗口View的measure过程

Android应用程序窗口View的layout过程

Android应用程序窗口View的draw过程

熟悉这三个过程,对我们自定义View很有帮助,但是分析上面过程中,对View的位置参数只是一笔带过,所以这里就再细说一下View的位置相关参数。

查看View的源码可以看几个我们常见的变量:

protected int mLeft;
protected int mRight;
protected int mTop;
protected int mBottom;
protected int mScrollX;
protected int mScrollY;首先看前面四个变量:



根据上图可以知道,mLeft是该View左上角的x轴方向坐标,mTop是该View左上角y轴方向的坐标,mRight该View右下角的x轴方向坐标,mBottom是该View右下角y轴方向的坐标。注意这些坐标值都是相对父容器,上面的围成矩形的宽高也就是View的宽高。在layout过程中就是根据这四个参数来确定View的位置的。

很明显.View的宽度等于mRight-mLeft,View的高度等于mBottom-mTop;

看View源码,查看getWidth(),getHeight()函数

public final int getWidth() {
return mRight - mLeft;
}
public final int getHeight() {
return mBottom - mTop;
}
获取这四个变量的函数是这样的
public final int getLeft() {
return mLeft;
}
public final int getTop() {
return mTop;
}
public final int getRight() {
return mRight;
}
public final int getBottom() {
return mBottom;
}同样有对应的set函数:
public final void setLeft(int left)
public final void setTop(int top)
public final void setRight(int right)
public final void setBottom(int bottom) 代码测试一把:
界面:



点击获取信息按钮,获取textview的顶点的坐标值和宽高:

int left = tv.getLeft();
int right = tv.getRight();
int top = tv.getTop();
int bottom = tv.getBottom();
int width = tv.getWidth();
int height = tv.getHeight();
Log.d("Test","left ="+left+" right="+right+" width="+width+" top="+top+" bottom="+bottom+" height="+height);

点击平移按钮,重新设置View的位置:

tv.setLeft(20);
tv.setTop(300);
tv.setRight(200);
tv.setBottom(360);
看一下平移后的效果:



看一下log:

平移前的log:

D/Test: left =0 right=269 width=269 top=252 bottom=340 height=88
平移后的log:
D/Test: left =20 right=200 width=180 top=300 bottom=360 height=60
顶点位置变化后,View的宽高也相应的发生变化了。
除了通过setLeft(),setTop,setRight,setBottom来改变View的位置外,还可以通过View的LayoutParams来改变View位置,例如:

LinearLayout.LayoutParams layoutParams1 = (LinearLayout.LayoutParams) tv.getLayoutParams();
layoutParams1.leftMargin = 10;
layoutParams1.rightMargin =400;
layoutParams1.topMargin = 30;
layoutParams1.topMargin = 90;
layoutParams1.width = 200;
layoutParams1.height = 200;这个就,没演示效果了。
从Android3.0开始,View增加了额外几个参数,x,y,translationX和translationY,其中x和y是View左上角的坐标,而tanslationX和translationY是View左上角相对于父容器的偏移量。这几个参数也是相对于父容器的坐标,并且translationX和translationY的默认值是0,有相应的set和get方法。

看一下View源码的相关函数:

public float getX() {
return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0);
}
public float getY() {
return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
}

public float getTranslationX() {
return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0;
}
public float getTranslationY() {
return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0;
}
可以得出上面提到的几个参数的关系:

x = mLeft + translationX 

y = mTop + translationY

咱们代码验证一下:

先看界面:



平移之前先获取相关位置信息:

int left = tv.getLeft();
int right = tv.getRight();
int top = tv.getTop();
int bottom = tv.getBottom();
int width = tv.getWidth();
int height = tv.getHeight();
Log.d("Test","left ="+left+" right="+right+" width="+width+" top="+top+" bottom="+bottom+" height="+height);

float translationX = tv.getTranslationX();
float translationY = tv.getTranslationY();
float x = tv.getX();
float y = tv.getY();
Log.d("Test","left ="+left+" translationX="+translationX+" x="+x+" top="+top+" translationY="+translationY+" y="+y);
平移之后:
tv.setTranslationX(50);
tv.setTranslationY(80);效果:



看一下log:

平移之前:

D/Test: left =0 right=269 width=269 top=252 bottom=340 height=88
D/Test: left =0 translationX=0.0 x=0.0 top=252 translationY=0.0 y=252.0
平移之后:
D/Test: left =0 right=269 width=269 top=252 bottom=340 height=88
D/Test: left =0 translationX=50.0 x=50.0 top=252 translationY=80.0 y=332.0
根据log,验证了前面mLeft x  translationX之前的关系。
而且还可以发现,通过setTranslationX,setTranslationY这种方式平移View的话,View的四个参数mLeft,mTop,mRight,mBottom都不会变。这四个参数是View的原始位置信息,平移后,原始信息保持不变,发生变化的是x,translationX,y,translationY这个四个参数。

下面继续讲一下mScrollX,mScrollY参数

要讲这两个参数,需要涉及到两个函数:在View类中

public void scrollTo(int x, int y)
public void scrollBy(int x, int y)
这个两个函数的作用是滚动视图内容,为什么说是视图内容而不是视图呢?记得之前讲View的绘制的时候有讲过,View绘制包括绘制好几部分

第一:首先画该View的背景
第二:画渐变框
第三:画该View本身的内容.比如textview就画自己text的内容,imagebutton就画所指的image...通过回调View的onDraw()函数开始绘制
第四:画自己的子View.当然前提是该View是ViewGroup类型.通过回调View的dispatchDraw()函数开始执行.dispatchDraw()函数在ViewGroup类里已经有默认实现了,函数里会分别调用子view的draw()函数去进行绘制,这样又是到上面的函数了.所以一般自定义的ViewGroup子类,不用去重写dispatchDraw()函数.只需要到自定义的子View的onDraw()函数绘制该view自己的内容.
第五:绘制scrollbar.
咱先看效果:
滚动之前



滚动之后:

调用方法

tv.scrollTo(30,40);

效果:



看到没有,只有视图内容发生滚动了,背景没有变化。

看一下scrollTo()scrollBy函数源码:

/**
* 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则实现了基于所传递参数的绝对滑动,这个不难理解。
看一下上面代码的log:

滚动之前:

D/Test: left =263 right=532 width=269 top=515 bottom=603 height=88
D/Test: left =263 translationX=0.0 x=263.0 top=515 translationY=0.0 y=515.0
D/Test: scrollX =0 scrollY=0
滚动之后:
D/Test: left =263 right=532 width=269 top=515 bottom=603 height=88
D/Test: left =263 translationX=0.0 x=263.0 top=515 translationY=0.0 y=515.0
D/Test: scrollX =30 scrollY=40getScrollX,getScrollY,分别可以获取mScrollX,mScrollY值。
mScrollX值就表示视图内容左边缘到mLeft的距离,注意有正负之分,如果是正值,视图内容的左边缘的值小于mLeft值,反之大于mLeft.

mScrollY值就表示视图内容上边缘到mTop的距离,注意有正负之分,如果是正值,视图内容的上边缘的值大于mTop的值,反之小于mTop.

所以上面我调用tv.scrollTo(30,40);视图内容的左边缘和上边缘已经滚出去了。

这个自己体会一下,或者亲自代码测试一下就知道结果了。

关于View的几个位置参数就讲这些了,通过对这些参数的进行操作,我们可以很简单实现平移View或者滑动View。再结合

源码分析Android触摸事件处理机制

处理触摸事件,就可以实现现在应用中常用到侧滑,下来刷新等效果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐