一、简介

  在安卓中,View代表视图,是安卓中十分重要的一个概念,重要程度不亚于四大组件,用户每时每刻都在与View打交道,包括展示数据、事件传递等。因此,熟练掌握View的应用以及原理是Android进阶的必经之路。最近笔者在学习任玉刚著的《Android 开发艺术探索》中的View的相关知识,便把学习心得及总结记录下来,与大家交流学习。

二、View的定义

  引用官方文档的描述:A View occupies a rectangular area on the screen and is responsible for drawing and event handling. 一个View占据一个矩形区域,负责绘制以及事件处理。所以一个View代表一个控件,我们平时接触的TextView,EditView,Button,ListView都是继承自View的。此外,除了View,还有一个ViewGroup,所谓ViewGroup是“控件组”,表示ViewGroup里面还有别的View,而且ViewGroup也是继承自View的。总的来说,View可以是单一的控件,也可是是许多控件组成的一组控件。

  为了说明View的层级关系,笔者创建了一个Demo,其层级关系如下图所示:笔者自定义了3个View,首先viewGroupA继承自ViewGroup,内部包含了一个viewGroupB;viewGroupB继承自ViewGroup,内部包含了一个viewA,而viewA继承自View。

三、View的几个重要参数

  对于一个View来说,最重要的莫过于位置参数了,因为这能标识一个View在哪,以及这个View的宽高,这对于一个View的绘制来说也很重要。一个View的位置的确定,取决于它的四个顶点,top(左上角纵坐标)、left(左上角横坐标)、bottom(右下角纵坐标)、right(右下角横坐标)。注意:以上坐标都是相对坐标,表示View相对于父布局的坐标。另外,在Android中,x轴和y轴的正方向分别为右和下。

  那么怎么获取这些参数呢?我们看看View的源码:

public class View implements Drawable.Callback, KeyEvent.Callback,AccessibilityEventSource {
...
protected int mLeft;
protected int mRight;
protected int mTop;
protected int mBottom;
...
}

  可以看出,View内有四个成员变量,分表代表了Top、Left、Right、Bottm的值,所以我们可以利用View的get方法获取这些值,比如说这样:

    int left = MyView.getLeft();
int top = MyView.getTop();
int right = MyView.getRight();
int bottom = MyView.getBottom()

  除了以上四个基本参数之外,还有x、y、translationX、translationY,类似地,安卓也提供了相应的get/set方法。接下来以一幅图来说明一下,这些参数的区别:

  由上图可总结如下:

  ①top、left、right、bottom代表View的初始坐标,在绘制完毕后就不会再改变

  ②translationX、translationY代表View左上角的偏移量(相对于父容器),比如上图是View进行了平移,那么translation代表水平平移的像素值,translationY代表竖直平移的像素值。

  ③x、y代表当前View左上角相对于父容器的坐标,即实时相对坐标。

  ④以上参数的关系可以用这两个公式表示:x = left + translationX 和y = right + translationY。

四、注意事项

  在使用View.getTop()、View.getX()等这些函数获取以上说到的参数时,有一个容易出错的地方,那就是不应该在onCreate()方法中直接获取,因为此时view还没还是绘制,所以得到的所有参数都会是0。以下结合一个Demo来说明这个问题:

  (1)先看布局以及布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.chenyu.viewbase.ViewGroupA
android:layout_width="400dp"
android:layout_height="400dp"
android:background="#4bd2c8"
android:layout_marginTop="50px"
android:layout_marginLeft="50px"
android:id="@+id/viewgroupA">
<com.chenyu.viewbase.ViewGroupB
android:id="@+id/viewgroupB"
android:layout_width="250dp"
android:layout_height="250dp"
android:background="#a07cf44e"
android:layout_marginTop="40px"
android:layout_marginLeft="40px">
<com.chenyu.viewbase.ViewA android:id="@+id/viewA"
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#cdd1d2"
android:layout_marginTop="30px"
android:layout_marginLeft="30px"/>
</com.chenyu.viewbase.ViewGroupB>
</com.chenyu.viewbase.ViewGroupA> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="获取参数"
android:id="@+id/button"
android:layout_below="@+id/viewgroupA"
android:layout_centerHorizontal="true" />
</RelativeLayout>

  (2)ViewGroupA、ViewGroupB、ViewA的代码基本相同,只不过ViewGroupA和ViewGroupB继承的是LinearLayout而ViewA继承的是View,所以只给出ViewGroupA的代码如下:

public class ViewGroupA extends LinearLayout {
public ViewGroupA(Context context) {
super(context);
}
public ViewGroupA(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ViewGroupA(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}

  (3)MainActivity:我们在onCreate()方法内先获取了ViewGroupA的坐标,然后在监听事件中再获取全部的坐标:

public class MainActivity extends Activity {
private LinearLayout viewGroupA;
private LinearLayout viewGroupB;
private View viewA;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewGroupA = (LinearLayout) findViewById(R.id.viewgroupA);
viewGroupB = (LinearLayout) findViewById(R.id.viewgroupB);
viewA = findViewById(R.id.viewA);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int viewGroupA_top = viewGroupA.getTop();
int viewGroupA_left = viewGroupA.getLeft();
Log.d("cylog", "viewGroupA的左上角坐标是:("+viewGroupA_left+","+viewGroupA_top+")");
int viewGroupB_top = viewGroupB.getTop();
int viewGroupB_left = viewGroupB.getLeft();
Log.d("cylog", "viewGroupB的左上角坐标是:("+viewGroupB_left+","+viewGroupB_top+")");
int viewA_top = viewA.getTop();
int viewA_left = viewA.getLeft();
Log.d("cylog", "viewA的左上角坐标是:("+viewA_left+","+viewA_top+")");
}
});
int viewGroupA_top = viewGroupA.getTop();
int viewGroupA_left = viewGroupA.getLeft();
Log.d("cylog", "viewGroupA的左上角坐标是:("+viewGroupA_left+","+viewGroupA_top+")");
}
}

  运行程序,并点击Button按钮,查看log日志:

  根据运行结果可知,在onCreate()方法内,是获取不到View的坐标参数的,因为此时View还未开始绘制,所以全部坐标参数都是0,由于在监听按钮事件的时候,View已经绘制完毕,此时才能获取参数。这是尤其需要注意的一点。同时可以看出,所打印的坐标都是相对于父布局的坐标。比如我们在布局文件中,设置了viewGroupA的margin_Top和margin_Left分别为50px和50px,此时viewGroupA的左上角坐标是(50,50),符合预期结果,同样地,viewGroupB(40,40)和viewA(30,30)都符合预期。

[Android UI]View基础知识的更多相关文章

  1. Android UI -- 的基础知识。

    在介绍基础知识之前先明确几个基本的概念 View 视图是所有可视组件的基类,所有的UI控件包括布局类都是从View派生出来的. ViewGroup ViewGroup是View的扩展,可以放置多个Vi ...

  2. View基础知识

    一.View基础知识 View 是Android中所有控件的基类,是一种界面层的控件的一种抽象,代表了一个控件 1.View的位置参数 View的四个属性:top(左上角纵坐标)     left(左 ...

  3. [Android UI]View滑动方式总结

    一.前言 在上一篇文章,介绍了View的坐标等基础知识,有了基础知识后,对下面内容的理解也将会容易很多.那么本文介绍的是View滑动的几种方式,这对于View来说,也是需要重要掌握的内容,因为用户无时 ...

  4. Android学习之基础知识十三 — 四大组件之服务详解第一讲

    一.服务是什么 服务(Service)是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务.服务的运行不依赖于任何用户界面,即使程序被切换到后台, ...

  5. Android学习之基础知识十五 — 最佳UI体验(Material Design实战)

    一.前言 长久以来,大多数人都认为Android系统的UI并不美观,至少没有iOS系统的美观.以至于很多IT公司在进行应用界面设计的时候,为了保证双平台的统一性,强制要求Android端的界面风格必须 ...

  6. Android学习之基础知识十一 —运用手机多媒体

    一.使用通知(Notification) 通知(Notification)是Android系统中比较有特色的一个功能,当某个应用程序希望向用户发出一些提示信息,而该应用程序又不在前台运行时,就可以借助 ...

  7. Android学习之基础知识五—创建自定义控件

    下面是控件和布局的继承关系: 从上面我们看到: 1.所有控件都是直接或间接继承View,所有的布局都是直接或间接继承ViewGroup 2.View是Android中最基本的UI组件,各种组件其实就是 ...

  8. Android手机分辨率基础知识(DPI,DIP计算)

    1.术语和概念 概念解释 名词 解释 Px (Pixel像素) 不同设备显示效果相同.这里的“相同”是指像素数不会变,比如指定UI长度是100px,那不管分辨率是多少UI长度都是100px.也正是因为 ...

  9. Android学习之基础知识十四 — Android特色开发之基于位置的服务

    一.基于位置的服务简介 LBS:基于位置的服务.随着移动互联网的兴起,这个技术在最近的几年里十分火爆.其实它本身并不是什么时髦的技术,主要的工作原理就是利用无线电通讯网络或GPS等定位方式来确定出移动 ...

随机推荐

  1. NSURLConnection基本用法(苹果原生)

    一.NSURLConnection的常用类 (1)NSURL:请求地址 (2)NSURLRequest/NSMutableURLRequest:封装一个请求,保存发给服务器的全部数据,包括一个NSUR ...

  2. CSS制作水平垂直居中对齐 多种方式各有千秋

    作为前端攻城师,在制作Web页面时都有碰到CSS制作水平垂直居中,我想大家都有研究过或者写过,特别的其中的垂直居中,更是让人烦恼.这段时间,我收 集了几种不同的方式制作垂直居中方法,但每种方法各有千秋 ...

  3. day36-hibernate检索和优化

    连接查询是多表查询.

  4. [poj3159]Candies(差分约束+链式前向星dijkstra模板)

    题意:n个人,m个信息,每行的信息是3个数字,A,B,C,表示B比A多出来的糖果不超过C个,问你,n号人最多比1号人多几个糖果 解题关键:差分约束系统转化为最短路,B-A>=C,建有向边即可,与 ...

  5. oracle 监听服务OracleOraDb11g_home1TNSListener打开后立马停止错误

    首先我真得吐槽一下,我安装这个破软件感觉真的是把能遇到的错误都遇到一遍了,生气!!!!!!! 关于监听服务OracleOraDb11g_home1TNSListener打开后立马停止这个错误,我的解决 ...

  6. Luogu 2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm

    基环树森林,然而我比较菜,直接tarjan找环. 发现缩点之后变成了DAG,每一个点往下走一定会走到一个环,缩点之后搜一遍看看会走到哪个环以及那个环的编号是多少,答案就是环的$siz$$ + $要走的 ...

  7. win10和ubuntu双系统下卸载ubuntu

    1.进入win10 2.下载EasyBCD,360软件管家里面有,version=2.2 3.启动软件,工具箱里面选择“BCD部署”→MBR配置选项中选“在MBR中安装Windows Vista/7的 ...

  8. 选择设置好ext3日志模式

    Linux是一种开放的.因Internet而产生的操作系统.Internet的发展.以网络为中心的计算模式如电子商务被迅速接受和普及,都为 Linux提供了更巨大的机会,使之成为企业和部门级的首选平台 ...

  9. 国内物联网平台(3):QQ物联智能硬件开放平台

    国内物联网平台(3)——QQ物联·智能硬件开放平台 马智 平台定位 将QQ帐号体系.好友关系链.QQ消息通道及音视频服务等核心能力提供给可穿戴设备.智能家居.智能车载.传统硬件等领域的合作伙伴,实现用 ...

  10. IOC与依赖注入

    spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和依赖查找,依赖什么?为什么需要依赖?注入什么?控 ...