黑马程序员技术交流社区

标题: Android控件建构与自定义控件详解 [打印本页]

作者: Android_Robot    时间: 2016-5-12 10:21
标题: Android控件建构与自定义控件详解
本帖最后由 Android_Robot 于 2016-10-19 15:10 编辑


Android控件建构与自定义控件详解

一、Android控件架构
       Android中的控件大致被分为两类:ViewGroup控件与View控件。
      ViewGroup控件作为父控件可以包含好多个View控件,并管理其包含的View控件。通过ViewGroup,整个界面上形成一个树结构,即控件树。下面看下Android界面架构图:

       从图中我们可以知道,每个Activity都包含一个Window对象,在Android中Window对象通常由PhoneWindow来实现PhoneWindow将一个DecorView设置为整个应用窗口的根View,在显示上它将屏幕分成两部分,一个是TitleView,另一个是ContentView,它是一个ID为content的Framelayout,所有我们通常会在onCreate方法中setContentView。

二、View的测量
          我们都知道在自定义控件的时候,我们在onMeasure()方法中进行控件的测量。Android系统给我们设计了一个功能强大的类MeasureSpec类,通过该类可以帮助我们测量View。MeasureSpec是一个32位的int值,其中高2位为测量的模式,低30位为测量的大小,使用位运算的目的就是提高并优化效率。测量模式可以分为三种:
  
       View类默认的onMeasure()方法中只支持EXACTLY模式,所以如果在自定义控件的时候不重写onMeasure()方法的话,就是默认的精确测量值模式。一般情况下我们都会重写onMeasure方法进行指定。我们通过查看源码,可以发现系统在测量的时候最终还是调用了setMeasuredDimension(int measuredWidth,int measuredHeight)方法将测量后的宽高设置进去。下面就给大家看一个测试的简单实例:
  1. @Override
  2.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  3.         int widthSize = MeasureSpec.getSize(widthMeasureSpec);
  4.         int widthMode = MeasureSpec.getMode(widthMeasureSpec);

  5.         int heightSize = MeasureSpec.getSize(heightMeasureSpec);
  6.         int heightMode = MeasureSpec.getMode(heightMeasureSpec);

  7.         if(heightMode == MeasureSpec.AT_MOST){
  8.                 heightSize = mDisplayMetrics.densityDpi * 30;
  9.         }
复制代码
       通过上面的简单实例,我们可以发现,首先获取我们所需要的测量模式,然后根据我们的需求进行指定。就是这么简单,就是这么easy。具体的效果,大家可以简单练习下。

三、View的绘制
       我们知道在view的绘制中,我们是在onDraw()方法中进行view的绘制。onDraw方法给我们提供了一个Canvas对象,让我们来绘制需要的东西。我们看下创建一个Canvas对象。
  1. Canvas canvas = new Canvas(bitmap);
复制代码
       在创建一个Canvas对象时,我们通常会将一个bitmap对象跟Canvas画布绑定在一起,这个过程称之为装载画布。这个bitmap存储所有绘制在canvas画板上的像素信息,所以当你使用这个canvas进行drawXXX方法时,信息都在bitmap上。

四、ViewGroup的测量
       在前面的分析中,我们知道ViewGroup中包含了很多的View对象,所以ViewGroup的大小同样是我们指定或者设置为wrap_content由子控件的大小控制,当设为wrap_content的时候,ViewGroup的大小就由内部分别遍历子View测量。当对子view测量完毕后,就执行View的Layout方法进行放置它们。

五、ViewGroup的绘制
          ViewGroup通常情况下不需要绘制,因为它本身就没有需要绘制的东西,如果不指定ViewGroup的背景颜色,那么ViewGroup的onDraw()方法都不会被调用。但是,ViewGroup会使用dispatchDraw()方法来绘制其子类View,其过程同样是遍历所有子View,并调用子View的绘制方法来完成的。

六、自定义View
       我们都知道自定义控件的恰当使用,能让我们的应用有亮点,但是滥用自定义View会带来适得其反的效果,一个让用户熟悉方便使用的控件测试好控件。在自定义View时,有以下几个重要的回调方法:

      通常情况下,自定义控件有以下三大类:
   (一)对现有控件的扩展
       我就不列举书中的例子了,就顺手给大家写一个例子吧!这个例子是实现解决这个问题的,我们默认情况下设置它的Gravity为居中,当获取焦点的时候,需要Gravity为左边,所以这个时候,我们为了这个小功能,不可能去重写写一个EditText,这里就可以对系统的控件进行扩充。代码如下:
  1. public class IOSEditText extends EditText {
  2.       public IOSEditText(Context context, AttributeSet attrs) {
  3.       super(context, attrs);
  4.       }

  5.      @Override
  6.      protected void onFocusChanged(boolean focused, int direction,
  7.      Rect previouslyFocusedRect) {
  8.             if(focused){
  9.                        setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
  10.             }else{
  11.                        setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
  12.            }
  13.      }
  14.     }
复制代码
这样就是一个简单的对现有控件扩展的例子。
(二)创建复合控件
       复合控件使用起来方便,比如我们的一个页面布局中,有很多重复类型的布局结构,这时我们就可以将它们抽取出来,做成复合控件,然后进行使用,这样也能减少代码的布局结构,具体例子就列出来了。这里涉及到的知识点有:
(三)重写View来实现全新控件
       这里就是我们的纯自定义控件。具体流程上面也有介绍,主要就是如何去实现绘制。传智·黑马自定义控件那两天的课程还是讲解的很精华的,好好学是可以领悟精髓的。

七、自定义ViewGroup
      前面我们已经简单介绍了自定义ViewGroup的基本流程。这一篇自定义ViewGroup帖子。

八、事件拦截机制分析
           在自定义控件中,事件的分发很重要:
          推荐几个相关精华资源:


至此,基本的知识点罗列出来,对照学习吧!

其他精华资源推荐:
【强荐!】2016年最新Android学习路线图——按此路线图学习月薪过万{ 火速收入}


作者: deqiqi939788736    时间: 2016-5-24 22:24
可以的!!!!!
作者: z736886202    时间: 2016-5-24 22:32
进来 顶一下  支持哟
作者: okchenyang44    时间: 2016-5-24 22:36
进来 顶一下  支持哟
作者: 119329    时间: 2016-5-25 00:00
支持  支持 受益
作者: 68846259    时间: 2016-5-25 18:49
mark........

作者: 68846259    时间: 2016-5-25 18:52
mark..........

作者: 飞奔的粽子    时间: 2016-5-25 23:25
涨姿势了
作者: jialp1024    时间: 2016-5-26 18:18
谢谢分享
作者: zhglyxgs    时间: 2016-5-26 21:13
马克一下,给楼主点赞
作者: 68帅锅    时间: 2016-5-26 23:31
顶贴走人
作者: adminn    时间: 2016-5-26 23:46
好好。。。。。
作者: 徐方锐    时间: 2016-5-27 00:21
进来顶一下,支持,加油
作者: wei19910428    时间: 2016-5-27 01:44
感谢楼主的分享
作者: android_vae    时间: 2016-5-27 18:35
有认真看,自定义View那讲的感觉不是很清楚,我也不太懂,但自定义的View规范讲(进行自定义的控件设计)应该需要重写onMeure类(可写可不写,看需要)和OnDraw类吧
作者: LRBlucky    时间: 2016-5-27 20:45
赞赞赞。。。。。。。。。
作者: static小白    时间: 2016-5-27 23:48
赞赞赞赞赞
作者: huhemingtiancai    时间: 2016-5-28 22:39
挺好的东西!正好我们用
作者: 聆听细雨    时间: 2016-5-28 23:14
下载下看看,好东西,顶一下
作者: woshijingke    时间: 2016-5-29 00:09

进来 顶一下  支持哟
作者: Kingchen    时间: 2016-5-29 22:13
顶一下!
作者: hmCEO    时间: 2016-5-29 23:28
学习了,不错
作者: dudubird    时间: 2017-1-16 15:31
可以的!!!!!
作者: 袁志娜    时间: 2017-1-17 23:59

作者: ha6cc    时间: 2017-7-2 22:36
非常感谢您的分享




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2