TimePicker源码学习-TimePicker的结构

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

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

spinner: 

TimePicker源码学习-TimePicker的结构

一、从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用到的类的关系

TimePicker源码学习-TimePicker的结构

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

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

TimePicker源码学习-TimePicker的结构

TimePicker源码学习-TimePicker的结构 

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

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

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

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

TimePicker源码学习-TimePicker的结构

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

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

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

相关推荐