`

Android自学笔记:Tab控件源码剖析

阅读更多
        此篇主要以画图的方式剖析Tab控件的使用方式和实现原理,以便对Tab控件有更深的理解和掌握。其实主要由于我的文笔太次,因此以图代字,不是有那么一句话么:一图胜千言;这种写作方式对技术文章来说,最为合适不过了。要有图,要有文字;要有火锅,要有美屡(这个不是错别字,有人能看懂)~~~

一、Tab初印象
        看图中画的框和椭圆,并对照着右边的文字说明,尽量看懂图中的包含关系。

       首先非常感谢 icoo1985 的指正,下面图中紫色框代表着是应用程序的范畴,也就是Acitivty,而不包含系统的状态栏。



二、Tab相关类的介绍及它们之间的关系
        在这一小节里,继续以图解的方式针对上一节中描述的包含关系和Tab构建过程进行阐述。
        1.TabActivity

        2.TabHost

        3.TabHost.TabSpec
        TabSpec主要负责去生成所需要添加进TabWidget和FrameLayout 布局当中的View,但是TabSpec不会直接与它们两个进行协作,而是只与TobHost来完成这一组装过程。按我的理解这个像是一个MVC模型,TabHost是控制器,TabSpec是模型,TabWidget和FrameLayout是视图展示层。
        下面两幅图是组装的过程展示,整体过程均在TabHost.addTab()完成。
        组装Indicator

        组装Content


三、剖析Tab控件的源码实现
        1.TabHost
        在第二节提到过一个方法setup (LocalActivityManager), 按照API文档上所说,仅在以Intent方式构建TabSpec时,才要显示调用这个方法,前提是你未继承TabActivity;换个简单的说法,继承了TabActivity,我们就不需要显式地调用这个方法。
        其实在setup (LocalActivityManager)版本中调用了它的重载版本setup(),也就是说真正的初始化工作是由setup来完成的。
        两者有个共特点就是一般都不会显示的调用它们,当它们不是以getTabHost()方式来创建的或者说就根本没继承TabActivity的话,则需要显示调用。比如下面的代码示例:
TabHost  mTabHost = (TabHost)findViewById(R.id.tabhost);
mTabHost.setup();//或者setup (getLocalActivityManager());
mTabHost.addTab(…);

        造成这种繁琐细节的主要原因是在于继承与不继承TabActivity。那么TabActivity已经为我们完成了这么的繁琐工作,那我们为什么不领这个情呢?
        2.TabHost.TabSpec
        在第二节中提到了TabHost.TabSpec的用途,就是用来构建View的,并只与TabHost打交道。它负责构建两种View,一个是indicator view,另一个则是content view。观其源码,很容易地看出来针对这两种View,都采用了策略模式。
        从实际用途的角度来考虑,创建Tab控件有共三种方式,这三种方式就对应着content view的三种策略,那么就先介绍它吧。
//TabHost.TabSpec 部分源码
//content view 构建策略引用
private ContentStrategy mContentStrategy;
//通过资源ID构建View
public TabSpec setContent(int viewId) {
    //该策略直截了当地调用findViewById()方法返回指定的视图
    mContentStrategy = new ViewIdContentStrategy(viewId);
    return this;
}
//通过资源Intent构建View
public TabSpec setContent(Intent intent) {
    //该策略LocalActivityManager.startActivity(String tabName, Intent intent)方法返回的Window,并通过Window的getDecorView() 返回最终的视图。
    mContentStrategy = new IntentContentStrategy(mTag, intent);
    return this;
}
//通过资源TabContentFactory构建View,它可以让你自由定制View
public TabSpec setContent(TabContentFactory contentFactory) {
    // FactoryContentStrategy,其内部维护着一个TabContentFactory引用,并调用createTabContent(tagName)方法返回定制化的视图。
    // 这个地方淋漓尽致地诠释了那句耳熟能详的名言,“将具体实现延迟到子类”,现在已经深有感触了。
    // 就拿这个例子来说,一开始不要想模式,先根据业务需求来考虑,这个content view会跟根据indicator而变化,所以要做一些if else的处理;为了考虑代码的可维护性和健壮性,代码写的一定要优雅,慢慢地慢慢地就重构成非常满意的效果了,一看,嘿!这不是工厂模式么。
    // 还有另外一种思考方式:当具备了一定的编码经验和设计经验之后,遇到该做活的地方一定要有一个意识,就好比提取出一个方法,我往这个方法传递各种参数已达到灵活的目的,慢慢地培养这种意识,代码就会越写越舒服了。
    mContentStrategy = new FactoryContentStrategy(mTag, contentFactory);
    return this;
}

        我不得不感叹TabHost.TabSpec中的策略模式设计得如此巧妙,仅仅通过重载方法就能够自由切换不同策略来构建View,继续往下看,我们回到TabHost. setCurrentTab(int index) 方法上,
// 仅用一行代码就获取了content view,非常优雅。
// mCurrentView是TabHost的成员变量,意指当前的content view。
// spec是通过index获取到的TabHost.Tabspec。
// mContentStrategy就是上面看到的策略接口引用。
// spec.mContentStrategy内部类的特性。
mCurrentView = spec.mContentStrategy.getContentView();


接下来我们看下indicator策略,如下:
//TabHost.TabSpec 部分源码
//indicator view 构建策略引用
private IndicatorStrategy mIndicatorStrategy;
//设置了indicator名,直接调用了TextView.setText()
public TabSpec setIndicator(CharSequence label) {
    mIndicatorStrategy = new LabelIndicatorStrategy(label);
    return this;
}
//设置了indicator名和indicator图片,直接调用了TextView.setText()和ImageView. setImageDrawable(),图片是icon类型的。
public TabSpec setIndicator(CharSequence label, Drawable icon) {
    mIndicatorStrategy = new LabelAndIconIndicatorStrategy(label, icon);
    return this;
}
//设置定制化的indicator view,API没有明确说明个方法,而只提到了上面的两个策略,不过定制view的思想还是值得提倡的。
 public TabSpec setIndicator(View view) {
    mIndicatorStrategy = new ViewIndicatorStrategy(view);
    return this;
}

通过观察,indicator view策略与content view策略如出一辙,但后者更为实用一些。
我们回到TabHost.addTab()方法上,
//也是仅用一行代码完成了获取indicator view的操作。
//由此看出来,学习设计模式固然重要,但写出优雅的代码势在必行!
View tabIndicator = tabSpec.mIndicatorStrategy.createIndicatorView();


四、总结
        经过一番分析,可以看出Tab控件是由多个控件组合而成的,每个控件各司其职,共同完成整体上的功能。
        个人感觉到分析的还是不太成熟,比较肤浅,思考的不够细致,怎么说呢,就是太感性了。今后会在分析问题上再多多下功夫,多多读源码,挖掘那些隐藏在表象之后的本质。


  • 大小: 88.9 KB
6
4
分享到:
评论
5 楼 YJ198910 2012-11-01  
分析得不错,有图有真相呀
4 楼 zhongyuanceshi 2012-05-28  
楼主强呀, ,请问,每个spec的title和icon是放在哪里?是不是每个app的重新赋值给title和icon,是哪个函数设置的
3 楼 深夜未眠 2011-03-25  
icoo1985 写道
tab的那张图里,紫色的框应该不包括系统的状态栏,应该是从Application那开始吧,博主的图画错了

哦 这个我还真没深入研究过呢,我回头去好好看一下;因为我也是自学的,有的东西也是靠着其它领域的经验推断出来的,惭愧惭愧- -
2 楼 icoo1985 2011-03-25  
tab的那张图里,紫色的框应该不包括系统的状态栏,应该是从Application那开始吧,博主的图画错了
1 楼 renpeng301 2011-03-03  
给力啊···

相关推荐

    Android自学笔记:Android2.3源码下载.docx

    这篇自学笔记详细介绍了在Windows环境下下载Android 2.3源码的步骤,这对于初学者尤其有用。首先,我们需要进行一些准备工作: 1. **下载Msysgit工具**:这是Windows系统下的Git客户端,可以从Google Code项目页面...

    Android应用开发完全自学手册

    第3章:Android控件入门 此章节主要介绍Android UI设计中的基本控件,如TextView、EditText、Button、ImageView等,以及如何在布局文件中使用XML来定义这些控件。同时,会教授如何在代码中动态添加和操作控件,以及...

    STM32自学笔记_stm32_STM32自学笔记_

    通过“STM32自学笔记”这样的资料,你可以系统地学习STM32的基础知识和实践技巧,逐步掌握单片机开发的全貌。在实践中,不断实验和调试,加深对外设的理解,是提升技能的关键。同时,参与社区交流,参考他人的项目,...

    STM32自学笔记.pdf

    [STM32自学笔记].蒙博宇

    Android自学笔记

    【Android自学笔记】 Android 应用开发是移动设备软件开发的重要领域,主要针对谷歌的Android操作系统。本笔记将概述Android应用开发的基础知识,包括环境搭建、应用构成、apk解析、Activity管理和生命周期等。 ...

    Java Web整合开发完全自学手册:Struts+Hibernate+Spring+Eclipse源码

    《JavaWeb整合开发完全自学手册》介绍如何整合Struts+Hibernate+Spring+Eclipse进行J2EE开发,所有实例都基于MyEclipseIDE开发,引领读者快速进入基于JavaWeb的J2EE应用领域。《JavaWeb整合开发完全自学手册》主要...

    小梅哥FPGA自学笔记书本源码

    《小梅哥FPGA自学笔记书本源码》是一份专为Verilog初学者设计的学习资源,由知名教育者“小梅哥”精心编写。这份资料以源码的形式呈现,包含多个章节,让学习者能够深入理解并实践Verilog语言的基础和高级特性。 ...

    FPGA自学笔记——设计与验证jmb.zip_FPGA设计_fpga_fpga 教程_verilog_设计与验证

    Verilog教程,小梅哥FPGA自学与验证

    Android自学笔记-11-listview简单例子

    本自学笔记将重点讲解如何在Android项目中创建并使用ListView,包括基本的设置、数据绑定和适配器的使用。 首先,我们需要在布局文件中添加ListView元素。在XML布局文件中,通过`<ListView>`标签定义ListView,可以...

    Android自学笔记-16-任务栈

    本自学笔记将深入探讨Android的任务栈机制,以帮助开发者更好地理解和利用这一特性来优化用户体验。 一、任务与任务栈 在Android中,一个任务(Task)是一个应用程序执行的上下文,它可以包含多个活动(Activity)...

    Android自学笔记(番外篇):全面搭建Linux环境(一)——前期准备工作

    这篇自学笔记将引导你逐步完成Linux环境的前期准备工作。首先,我们需要理解为何要选择Linux,尤其是在Android开发中。 Linux是一个开源、免费的操作系统,它提供了强大的命令行工具和灵活的环境配置,对于开发者来...

    读书笔记:Java从入门到精通自学代码.zip

    读书笔记:Java从入门到精通自学代码

    STM8单片机自学笔记-范红刚著

    STM8单片机自学笔记-范红刚著, 单片机自学系列的STM8自学教程,, 推荐给大家, 这个系列我一直在收集. 清爽版本

    计算机网络自学笔记

    计算机网络自学笔记: 一、计算机网络基础 1. 计算机网络的定义 计算机网络是由多台计算机及相关设备组成,通过通信介质实现资源共享和信息交换的系统。网络中的设备可以通过特定的网络协议进行通信,而Internet...

    《STM32自学笔记》随书共享资料

    《STM32自学笔记》随书共享资料包含了学习STM32开发所必需的各种资源,包括书籍配套的光盘资料和STM32的3.5数据库及使用手册。 首先,STM32的3.5数据库可能是关于STM32的固件库或HAL库的更新版本,这些库为开发者...

    《Android逆向自学笔记》.pdf

    Android逆向自学笔记

    STM32自学笔记 随书资料

    本资源“STM32自学笔记 随书资料”是一份全面的学习STM32开发的参考资料,旨在帮助初学者快速入门并深入理解STM32的工作原理和编程技巧。 一、STM32架构与特性 STM32系列涵盖了多种型号,主要基于Cortex-M0、M3、M4...

    Android自学笔记-13-ContentObserver内容观察者

    本自学笔记将深入探讨ContentObserver的工作原理、使用场景以及如何实现它。 ContentObserver主要用于监控ContentResolver中的内容更改,这些内容通常存储在ContentProvider中。当某个ContentProvider的数据发生...

Global site tag (gtag.js) - Google Analytics