TimePicker源码学习-TimePicker的结构

  虽然自己也看过很多的Android源码,也看过很多别人写的源码分析,但是总觉得写出来的东西并不能完全展现代码作者所写的东西或者自己看源码的思维过程。(无法用言语形容)

  这篇文章对常用的时间选择器TimePicker源码的总结,我可能不会从头一步一步的分析源代码,仅是我看完后的总结,当然也从中学习并应用后才有的总结。

  spinner: 

一、从TimePicker.java看起

  1.TimePicker继承FrameLayout,表明TimePicker只是用于布局而不是具体的绘制,具体的绘制view肯定在另外的地方画,然后再布局到这个FrameLayout上面(这个很关键!为什么?) 

public class TimePicker extends FrameLayout{
    //......
}

  2.首先从TimePicker构造方法看起

  在这里看到了MODE_CLOCK和MODE_SPINNER,分别是TimePicker的两种形式(可以在布局中对timePickerMode属性设置clockt或者spinner),一种对应TimePickerClockDelegate,另外一种对应的是TimePickerSpinnerDelegate。要注意this就是TimePicker,并且TimePicker被传进了mDelegate 的构造参数里面去。可以看到选择时间器最后要在mDelegate中进行绘制并布局在mDelegate 中。

public TimePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);

    final TypedArray a = context.obtainStyledAttributes(
            attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes);
    final int mode = a.getInt(R.styleable.TimePicker_timePickerMode, MODE_SPINNER);
    a.recycle();

    switch (mode) {
        case MODE_CLOCK:
            mDelegate = new TimePickerClockDelegate(
                    this, context, attrs, defStyleAttr, defStyleRes);
            break;
        case MODE_SPINNER:
        default:
            mDelegate = new TimePickerSpinnerDelegate(
                    this, context, attrs, defStyleAttr, defStyleRes);
            break;
    }
}

  下面我们转移到TimePickerClockDelegate,因为TimePickerSpinnerDelegate对相应的,没有必要两个都分析

二、再看TimePickerClockDelegate.java,

  1.也是从构造方法看起,

  在构造方法的中用一段inflate代码,用于对layout文件进行展开。可以看出,layout内容展开到delegator里面,而这个就是TimePicker!!这时我们就知道为什么TimePicker是继承FrameLayout的了,从上面可以看到Timepicker构造的时候已经传进来。

//下面是TimePickerClockDelegate.java的代码:
final int layoutResourceId = a.getResourceId(R.styleable.TimePicker_internalLayout,
R.layout.time_picker_material);
final View mainView = inflater.inflate(layoutResourceId, delegator);

mHeaderView = mainView.findViewById(R.id.time_header);

  另外我们可以对比一下TimePickerClockDelegate和TimePickerSpinnerDelegate这段代码,发现风格有点不一样,可能是两个人或者同一个人在不同的时间写的,

//下面是TimePickerSpinnerDelegate.java的:
final LayoutInflater inflater = LayoutInflater.from(mContext);
inflater.inflate(layoutResourceId, mDelegator, true);

// hour
mHourSpinner = (NumberPicker) delegator.findViewById(R.id.hour);

  2.以下我再汇总了TimePickerClockDelegate的成员变量,并形成TimePicker的类图结构

  从中你可以看到TimePicker用到的类的关系

3.TimePickerClockDelegate是一个组合式的自定义view

  从TimePickerClockDelegate代码你可以看到他里面没有onDraw方法,说明他是一个组合式的自定义view

  

  再从类图中看他的成员变量和timepicker中clock显示模式可以看出,表盘是在RadialTimePickerView里面画的,即  

  RadialTimePickerVIew:时钟式的时间选择器中的表盘,

其他TextView:显示的小时数和分钟数,上下午显示等(看TimePickerCLockDelegate的成员变量就可以知道)

  4.所以最后也是最重要的就是表盘RadialTimePickerVIew的绘制,他里面的知识或者思想可以用在很多的地方。比如一个文字两种颜色或背景色(其实就是用到了画图区域的补集和余集知识)。

    

  总结:本文主要讲述Android中的TimePicker类的代码结构,代码细节没有太细的深究,从中可以学到不少知识。

      1)比如如果一个自定义控件比较复杂,可以把它分解,然后再组合成一个整体。

      2)为了扩展或者兼容,可以采用代理的模式,由代理完成具体的实现。

时间: 2024-07-30 13:44:08

TimePicker源码学习-TimePicker的结构的相关文章

[Go语言]从Docker源码学习Go——结构和函数的定义

Docker在最近很火,而作为Docker的开发语言-Go也再次被大家提到. 已经使用Docker一段时间了,但是对于源码,尤其是其开发语言Go却一直是一知半解. 最近准备利用空余时间从Docker源代码入手来学习一下Go,同时对Docker的实现也希望可以提高一个层次. 有兴趣的可以一起讨论,学习. 准备工作: 1. Docker源代码https://github.com/docker/docker (版本1.1.2) 2. 安装开发工具LiteIDE, 这个是官方的Go语言的IDE 3. G

[Go语言]从Docker源码学习Go——if语句和map结构

if语句 继续看docker.go文件的main函数 if reexec.Init() { return } go语言的if不需要像其它语言那样必须加括号,而且,可以在判断以前,增加赋值语句 语法 IfStmt = "if" [ SimpleStmt ";" ] Expression Block [ "else" ( IfStmt | Block ) ] . 例子 if x := f(); x < y { return x } else i

MINA2 源码学习--源码结构梳理

一.mina的整体框架结构及案例: 1.整体结构图: 简述:以上是一张来自网上比较经典的图,整体上揭示了mina的结构,其中IoService包含客户端IoConnector和服务端IoAcceptor两部分.即无论是客户端还是服务端都是这个结构.IoService封装了网络传输层(TCP和UDP),而IoFilterChain中mina自带的filter做了一些基本的操作之外,支持扩展.经过FilterChain之后最终调用IoHandler,IoHandler是具体实现业务逻辑的处理接口,具

jquery源码学习

jQuery 源码学习是对js的能力提升很有帮助的一个方法,废话不说,我们来开始学习啦 我们学习的源码是jquery-2.0.3已经不支持IE6,7,8了,因为可以少学很多hack和兼容的方法. jquery-2.0.3的代码结构如下 首先最外层为一个闭包, 代码执行的最后一句为window.$ = window.jquery = jquery 让闭包中的变量暴露倒全局中. 传参传入window是为了便于压缩 传入undefined是为了undifined被修改,他是window的属性,可以被修

storm源码之storm代码结构【译】【转】

[原]storm源码之storm代码结构[译] 说明:本文翻译自Storm在GitHub上的官方Wiki中提供的Storm代码结构描述一节Structure of the codebase,希望对正在基于Storm进行源码级学习和研究的朋友有所帮助. Storm的源码共分为三个不同的层次. 首先,Storm在设计之初就考虑到了兼容多语言开发.Nimbus是一个thrift服务,topologies被定义为Thrift结构体.Thrift的运用使得Storm可以被任意开发语言使用. 其次,Stor

JDK源码学习系列08----HashMap

                                                          JDK源码学习系列08----HashMap 1.HashMap简介 HashMap 是一个散列表,它存储的内容是键值对(key-value)映射. HashMap 继承于AbstractMap,实现了Map.Cloneable.java.io.Serializable接口. HashMap 的实现不是同步的,这意味着它不是线程安全的.它的key.value都可以为null.此外,

lua源码学习(一)lua的c api外围实现

工作后,整个人已经比较松懈了.虽然一直在看lua的源码,但是一直是比较零碎的时间,没有系统的整理,所以还是收获不多.因为最近工作也不是很忙了,就想整理下lua的源码学习的笔记,加深下印象,并分享给大家. 先说下这系列bolg我会每周更新2-3篇,没有顺序的 这些文章都是自己的浅薄的理解,有什么错误,还请各位拍砖赐教. 1.关于c语言函数的声明 相信大家都知道接口的重要,在lua中,如果要调用c语言的函数,就必须要有一个统一的函数声明: typedef int (*lua_CFunction) (

JDK源码学习LinkedList

LinkedList是List接口的子类,它底层数据结构是双向循环链表.LinkedList还实现了Deque接口(double-end-queue双端队列,线性collection,支持在两端插入和移除元素).所以LinkedList既可以被当作双向链表,还可以当做栈.队列或双端队列进行操作.文章目录如下: 1.LinkedList的存储实现(jdk 1.7.0_51) 2.LinkedList的读取实现 3.LinkedList的性能分析 下面我们进入正题,开始学习LinkedList. L

JDK源码学习----ArrayList

                                                                         JDK源码学习----ArrayList 1.ArrayList简介 ArrayList是基于Object[] 数组的,也就是我们常说的动态数组.它能很方便的实现数组的增加删除等操作. public class ArrayList<E> extends AbstractList<E> implements List<E>, R