一、View的种类
View主要分成两种:
- 一种是单一视图,只包含一个view,常见的有textview等。
- 另一种是视图组,包含一组view,也就是viewgroup。可以看到viewgroup继承自view,比如Linearlayout等布局、listview。
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
}
所以可以说Android中所有的UI组建都是继承自view。
二、View的层级关系
-
PhoneWindow是Android系统中最基本的窗口系统,继承自Windows类,负责管理界面显示以及事件响应。它是Activity与View系统交互的接口
-
DecorView是PhoneWindow中的起始节点View,继承于View类,作为整个视图容器来使用。用于设置窗口属性。它本质上是一个FrameLayout,包含了一个通知栏TitleView和ContentView。contentview我们可以说是非常熟悉了。每次在activity oncreate中指定布局用的setContentView所指定的就是这个ContentView
对于多view的视图组来说,是以树形结构存在的。
最顶层是一个ViewGroup,它的子节点既可以是View,也可以是ViewGroup。无论是measure过程、layout过程还是draw过程,都是从父节点依次到子节点的遍历,直到遍历到所有节点。
三、View的位置参数
Android 的坐标系和我们常见的数学坐标系略有不同,Android的坐标系定义为:
-
屏幕的左上角为坐标原点
-
向右为x轴增大方向
-
向下为y轴增大方向
如图所示
1.left right top bottom
View 的4个顶点的位置描述分别由4个值决定:
请记住:View的位置是相对于父控件而言的),即是相对坐标
-
Top:子View上边界到父view上边界的距离
-
Left:子View左边界到父view左边界的距离
-
Bottom:子View下边距到父View上边界的距离
-
Right:子View右边界到父view左边界的距离
所以我们可以很轻松的表示四个点的坐标,例如左上角的顶点可以表示为(left,top)
它们的值可以通过getXXX()方法获取,例如getTop()
2.x y translationX translationY
在Android 3.0后新增了x,y,translationX,translationY这四个属性,它们的换算关系如下所示
默认情况下translation=0 ,即left = x ,top = y
3.那么translation有什么作用?xy和left top有什么区别呢?
比如我们水平平移view时,改变的是translationX 和 x的值,而left不会改变。因为left代表的是原始view左边界距离父左边届的距离。有点难以理解,请看例子。
代码很简单,由于在onCreate中还未绘制view,所以这里用post获取到未点击前的textview的宽高和位置
此外还有一个点击事件,点击后将x增加100
public class MainActivity extends AppCompatActivity {
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.myText);
textView.post(new Runnable() {
@Override public void run() {
Log.d("MainActivity",
"left =" + textView.getLeft() + " ,top = " + textView.getTop());
Log.d("MainActivity", "x =" + textView.getX() + " ,y = " + textView.getY());
Log.d("MainActivity",
"width =" + textView.getWidth() + " ,height = " + textView.getHeight());
}
});
textView.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
//textView.setLeft(textView.getLeft()+100);
textView.setX(textView.getX());
Log.d("MainActivity_onclick",
"left =" + textView.getLeft() + " ,top = " + textView.getTop());
Log.d("MainActivity", "x =" + textView.getX() + " ,y = " + textView.getY());
Log.d("MainActivity",
"width =" + textView.getWidth() + " ,height = " + textView.getHeight());
}
});
}
}
看一下效果图和打印输出的日志
效果图
log输出
可以观察到,left并没有变化,变化的是x,并且view向右移动了300像素。
那么假如我们改变left有什么效果呢?
效果图
log输出
可以很神奇地看到修改left并不会移动view,只会单纯地修改view的左边届与父布局左边届的距离,但是其他边界都不会修改。此外它的宽度还发生了变化。
看一下getwidth的源码,width的取值就是right-left。height同理
/**
* Return the width of your view.
*
* @return The width of your view, in pixels.
*/
@ViewDebug.ExportedProperty(category = "layout")
public final int getWidth() {
return mRight - mLeft;
}