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;首先看前面四个变量:
![](http://img.blog.csdn.net/20161122145857469?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
根据上图可以知道,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) 代码测试一把:
界面:
![](http://img.blog.csdn.net/20161122161143900?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
点击获取信息按钮,获取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);
看一下平移后的效果:
![](http://img.blog.csdn.net/20161122161428689?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
看一下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
咱们代码验证一下:
先看界面:
![](http://img.blog.csdn.net/20161122164324450?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
平移之前先获取相关位置信息:
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);效果:
![](http://img.blog.csdn.net/20161122164437672?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
看一下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.
咱先看效果:
滚动之前
![](http://img.blog.csdn.net/20161122170802725?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
滚动之后:
调用方法
tv.scrollTo(30,40);
效果:
![](http://img.blog.csdn.net/20161122170856663?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
看到没有,只有视图内容发生滚动了,背景没有变化。
看一下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触摸事件处理机制
处理触摸事件,就可以实现现在应用中常用到侧滑,下来刷新等效果。
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触摸事件处理机制
处理触摸事件,就可以实现现在应用中常用到侧滑,下来刷新等效果。
相关文章推荐
- Android-区分 View 的 translationX、Y , X、Y 和 Left、Top,Right、Bottom
- View的位置--top, left, bottom, right
- Andriod中绘(画)图----Canvas的使用详解 (附canvas.drawRect(left, top, right, bottom, paint)参数理解)
- Android控件设置——动态View的drawableLeft/ drawableRight/drawableTop/drawableBottom
- 【Android】TextView动态设置android:drawableLeft|Right|Top|Bottom,SetColor
- Android view 的参数x y left right top bottom translationX translationY
- View滑动动画的选择及其left, marginLeft, translationX参数的总结
- 面试总结(4):top、left、right、bottom 和 translationX、translationY 和 scrollX,scrollY的区别
- View[2] left、top、right、bottom
- android关于TextView的drawableLeft,drawableTop,drawableRight,drawableRight的drawable大小及位置问题
- TextView 代码设置drawableLeft、drawableRight、drawableTop、drawableBottom
- 获得View在布局和屏幕上的位置(getLeft()以及getLocationOnScreen())
- 动态设置android:drawableLeft|Right|Top|Bottom
- CareerCup View from the left and the right
- matlab 标定箱错误:Disabling view 2 - Reason: the left and right images are found inconsistent (已解决)
- 自定义控件让TextView、Button的drawableLeft和drawableRight与文本一起居中显示
- Android View坐标getLeft, getRight, getTop, getBottom解惑
- css中的relative相对定位的top bottom left right
- 动态设置android:drawableLeft|Right|Top|Bottom
- left right top bottom定位div无效