1. 作过Android 应用开发的朋友都知道,Android的UI界面都是由View和ViewGroup及其派生类组合而成的。其中,View是所有UI组件的基类,而ViewGroup是容纳这些组件的容器,其本身也是从View派生出来的。AndroidUI界面的一般结构可参见下面的示意图:

可见,作为容器的ViewGroup可以包含作为叶子节点的View,也可以包含作为更低层次的子ViewGroup,而子ViewGroup又可以包含下一层的叶子节点的View和ViewGroup。事实上,这种灵活的View层次结构可以形成非常复杂的UI布局,开发者可据此设计、开发非常精致的UI界面。

一般来说,开发Android应用程序的UI界面都不会直接实用View和ViewGroup,而是使用这两大基类的派生类。

View派生出的直接子类有:AnalogClock,ImageView,KeyboardView, ProgressBar,SurfaceView,TextView,ViewGroup,ViewStub

View派生出的间接子类有:AbsListView,AbsSeekBar, AbsSpinner, AbsoluteLayout, AdapterView<T extends Adapter>,AdapterViewAnimator, AdapterViewFlipper, AppWidgetHostView, AutoCompleteTextView,Button,CalendarView, CheckBox, CheckedTextView, Chronometer, CompoundButton,

ViewGroup派生出的直接子类有:AbsoluteLayout,AdapterView<T extends Adapter>,FragmentBreadCrumbs,FrameLayout,LinearLayout,RelativeLayout,SlidingDrawer

ViewGroup派生出的间接子类有:AbsListView,AbsSpinner, AdapterViewAnimator, AdapterViewFlipper, AppWidgetHostView, CalendarView, DatePicker, DialerFilter, ExpandableListView, Gallery, GestureOverlayView,GridView,HorizontalScrollView, ImageSwitcher,ListView,

上面View、ViewGroup的直接子类和间接别子类中标记为红色的类是我们再应用开发中接触和用得比较频繁的类,需要初学者重点熟悉和掌握,其详细的API及用法可参见SDK的说明。这里特别指出,ImageView是布局具有图片效果的UI常用的类,SurfaceView是用来进行游戏开发的与一般View相比较为特殊的非常重要的类(后续会对原理作深入分析),而AbsoluteLayout、FrameLayout,LinearLayout, RelativeLayout这几个ViewGroup的直接子类是Android UI布局中最基本的布局元素。

值得一提的是,上述的所有基类、派生类都是Android framework层集成的标准系统类,开发者在应用开发中可直接引用SDK中这些系统类及其API。但事实上,在UI开发的很多场景下,直接使用这些系统类并不能满足应用开发的需要。比如说,我们想用ImageView在默认情况下加载一幅图片,但是希望在点击该View时View变换出各种图像处理效果,这个时候直接使用ImageView是不行的,此时我们可以重载ImageView,在新派生出的子控件中重载OnDraw等方法来实现我们的定制效果。这种派生出系统类的子类方法我们通常称之为自定义控件。自定义控件可像标准View控件那样在XML及我们的Java文件中进行布局和实例化,但在布局时必须指出其完整的包名和类名。事实上,自定义控件的使用是我们进行Android 开发的必不可少的基本用法,是必须掌握的基本技巧。

2. 下面我们来看一个典型的例子,我们待机Launcher 的XML布局,这个例子能够很好的说明上面的一些概念。

 <?xml version="1.0" encoding="utf-8"?>

 <!-- Copyright (C) 2007 The Android Open Source Project

      Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. --> <com.android.launcher2.DragLayer
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
android:id="@+id/drag_layer"
android:layout_width="match_parent"
android:layout_height="match_parent"> <include layout="@layout/all_apps" /> <!-- The workspace contains 3 screens of cells --> <com.android.launcher2.Workspace
android:id="@+id/workspace"
android:layout_width="match_parent"
android:layout_height="match_parent"
launcher:defaultScreen="2"> <include android:id="@+id/cell1" layout="@layout/workspace_screen" /> <include android:id="@+id/cell2" layout="@layout/workspace_screen" /> <include android:id="@+id/cell3" layout="@layout/workspace_screen" /> <include android:id="@+id/cell4" layout="@layout/workspace_screen" /> <include android:id="@+id/cell5" layout="@layout/workspace_screen" />
</com.android.launcher2.Workspace> <ImageView
android:id="@+id/previous_screen"
android:layout_width="93dip"
android:layout_height="@dimen/button_bar_height"
android:layout_gravity="bottom|left"
android:layout_marginLeft="6dip"
android:scaleType="center"
android:src="@drawable/home_arrows_left"
android:onClick="previousScreen"
android:focusable="true"
android:clickable="true" /> <ImageView
android:id="@+id/next_screen"
android:layout_width="93dip"
android:layout_height="@dimen/button_bar_height"
android:layout_gravity="bottom|right"
android:layout_marginRight="6dip"
android:scaleType="center"
android:src="@drawable/home_arrows_right"
android:onClick="nextScreen"
android:focusable="true"
android:clickable="true" /> <com.android.launcher2.DeleteZone
android:id="@+id/delete_zone"
android:layout_width="@dimen/delete_zone_size"
android:layout_height="@dimen/delete_zone_size"
android:paddingTop="@dimen/delete_zone_padding"
android:layout_gravity="bottom|center_horizontal"
android:scaleType="center"
android:src="@drawable/delete_zone_selector"
android:visibility="invisible"
launcher:direction="horizontal"
/> <RelativeLayout
android:id="@+id/all_apps_button_cluster"
android:layout_width="fill_parent"
android:layout_height="@dimen/button_bar_height"
android:layout_gravity="bottom|center_horizontal"
android:paddingTop="2dip"
> <com.android.launcher2.HandleView
style="@style/HotseatButton"
android:id="@+id/all_apps_button"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:src="@drawable/all_apps_button"
launcher:direction="horizontal"
/> <ImageView
android:id="@+id/hotseat_left"
style="@style/HotseatButton.Left"
android:layout_toLeftOf="@id/all_apps_button"
android:src="@drawable/hotseat_phone"
android:onClick="launchHotSeat"
/> <ImageView
android:id="@+id/hotseat_right"
style="@style/HotseatButton.Right"
android:layout_toRightOf="@id/all_apps_button"
android:src="@drawable/hotseat_browser"
android:onClick="launchHotSeat"
/> </RelativeLayout>
</com.android.launcher2.DragLayer>

在上面的XML布局中,最顶层的控件com.android.launcher2.DragLayer是一个自定义控件,其继承自ViewGroup的直接子类FrameLayout。在DragLayer的布局内部,其子View既有ImageView类本身,也有从ImageView的派生出的子定义控件HandleView,既有ViewGroup的框架中的直接子类RelativeLayout,也有从派生出的自定义控件Workspace。总之,这布局的例子是大家学习Android布局、应用开发和理解Android View、ViewGroup概念的非常优秀的例子,大家可下载Launcher模块的源代码来进行深入分析(Launcher单个模块的下载方法可参见博文Android源码下载——用git clone实现单个目录下载 )。

最后,给大家介绍下View和ViewGroup最重要的几个方法:
protected void onDraw(Canvas canvas):View类中用于重绘的方法,这个方法是所有View、ViewGroup及其派生类都具有的方法,也是Android UI绘制最重要的方法。开发者可重载该方法,并在重载的方法内部基于参数canvas绘制自己的各种图形、图像效果。
protected void onLayout(boolean changed, int left, int top, int right, int bottom):View类中布局发生改变时会调用的方法,这个方法是所有View、ViewGroup及其派生类都具有的方法,重载该类可以在布局发生改变时作定制处理,这在实现一些特效时非常有用。
protected void dispatchDraw(Canvas canvas):ViewGroup类及其派生类具有的方法,这个方法主要用于控制子View的绘制分发,重载该方法可改变子View的绘制,进而实现一些复杂的视效,典型的例子可参见Launcher模块Workspace的dispatchDraw重载。
protected boolean drawChild(Canvas canvas, View child, long drawingTime)):ViewGroup类及其派生类具有的方法,这个方法直接控制绘制某局具体的子view,重载该方法可控制具体某个具体子View。

View、ViewGroup是Android UI体系至关重要的两大基类,本文仅对一些最基本的概念、原理和API进行了介绍,大家要全面掌握还需要阅读SDK中对这两个类的介绍并熟悉其API ,并在应用开发中逐渐的加深理解和掌握其用法。

Android(java)学习笔记95:Android原理揭秘系列之View、ViewGroup的更多相关文章

  1. Android(java)学习笔记34:Android原理揭秘系列之View、ViewGroup

    1. 作过Android 应用开发的朋友都知道,Android的UI界面都是由View和ViewGroup及其派生类组合而成的.其中,View是所有UI组件的基类,而ViewGroup是容纳这些组件的 ...

  2. Android开发学习笔记-关于Android的消息推送以及前后台切换

    下面是最简单的Android的消息推送的实现方法 package com.example.shownotic; import java.util.Random; import android.supp ...

  3. Android 数字签名学习笔记

    Android 数字签名学习笔记 在Android系统中,所有安装到系统的应用程序都必有一个数字证书,此数字证书用于标识应用程序的作者和在应用程序之间建立信任关系,如果一个permission的pro ...

  4. Android动画学习笔记-Android Animation

    Android动画学习笔记-Android Animation   3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中 ...

  5. Android:日常学习笔记(6)——探究活动(4)

    Android:日常学习笔记(6)——探究活动(4) 活动的启动模式 standard模式 standard是活动默认的启动模式,在不进行显示定义的情况下,所有活动都会自动使用这种启动模式. stan ...

  6. Android Studio 学习笔记(一)环境搭建、文件目录等相关说明

    Android Studio 学习笔记(一)环境搭建.文件目录等相关说明 引入 对APP开发而言,Android和iOS是两大主流开发平台,其中区别在于 Android用java语言,用Android ...

  7. Android自动化学习笔记:编写MonkeyRunner脚本的几种方式

    ---------------------------------------------------------------------------------------------------- ...

  8. Android自动化学习笔记之MonkeyRunner:官方介绍和简单实例

    ---------------------------------------------------------------------------------------------------- ...

  9. android开发学习笔记000

    使用书籍:<疯狂android讲义>——李刚著,2011年7月出版 虽然现在已2014,可我挑来跳去,还是以这本书开始我的android之旅吧. “疯狂源自梦想,技术成就辉煌.” 让我这个 ...

随机推荐

  1. 【Hadoop代码笔记】Hadoop作业提交之Child启动reduce任务

    一.概要描述 在上篇博文描述了TaskTracker启动一个独立的java进程来执行Map任务.接上上篇文章,TaskRunner线程执行中,会构造一个java –D** Child address ...

  2. Signs of a poorly written jQuery plugin 翻译 (Jquery插件开发注意事项,Jquey官方推荐)

    原文链接:http://remysharp.com/2010/06/03/signs-of-a-poorly-written-jquery-plugin/ 原文作者:remy sharp So far ...

  3. New full duplex HTTP tunnel implementation (client and server)

    https://issues.jboss.org/browse/NETTY-246?page=com.atlassian.jirafisheyeplugin:fisheye-issuepanel —— ...

  4. red5下nginx安装配置

    http://zfl110.iteye.com/blog/1155149 原址:http://lqw.iteye.com/blog/652763 安装Nginx 1.首先安装pcre-8.02.tar ...

  5. [iOS基础控件 - 6.12.2] Modal

    A.概念 1.也可以用来切换控制器 2.如ActionSheet   除了push之外,还有另外一种控制器的切换方式,那就是Modal 任何控制器都能通过Modal的形式展示出来 Modal的默认效果 ...

  6. linux下登陆用户的行为信息—w和who命令详解

    查看用户的操作系统管理员若想知道某一时刻用户的行为,只需要输入命令w 即可,在SHELL终端中输入如下命令: [root@localhost ~]# w 可以看到执行w命令及显示结果. 命令信息含义上 ...

  7. UVaLive 7363 A Rational Sequence (二叉树)

    题意:给定一个二叉树,并对每一个进行编号和规定,现在给你一个值,问你是第几个. 析:这个题,我想了好久才想出来,这个真是数据结构练的太差了,不够扎实,这个题,应该从下向上推,如果分子大于分母,那么这个 ...

  8. PHP- Windows无法在本地计算机启动Apache的解决方法

    装好了WAMP,开始可以进行我的PHP学习了.可是装后却打不开locahost. 百度后如下解决了:"Windows不能在本地计算机启动Apache2.有关更多信息,查阅系统事件日志.如果这 ...

  9. delete数组引发的core分析

    delete [] ptr 引发了singnal 6 abort的core错误,跟踪过程发现写入ptr大量数据,引发内存越界,破坏了new数组的尾部数据保护,导致delete的时候core. 问题分析 ...

  10. [c++]this指针理解

    #include <iostream> using namespace std; /** * this 指针理解 */ class A{ int i; public: void hello ...