Android开源代码解读-基于SackOfViewAdapter类实现类似状态通知栏的布局
一般来说,ListView的列表项都会采用相同的布局,只是填充的内容不同而已,这种情况下,Android提供了convertView帮我们缓存列表项,达到循环利用的目的,开发者也会使用ViewHolder模式来对ListView进行优化。但有的情况下,ListView的列表项布局是不尽相同的,甚至差别很大,这时就不能简单的使用同一个布局资源文件来表示不同类型的列表项了,而是必须区别对待。典型的情况如Android状态通知栏,如下图所示。

360安全卫士、唱吧,闪推这三款应用在状态通知栏的布局差别很大,那么我们又想使用同一个Adapter来表示不同列表项,这时就需要在Adapter中使用容器来包含这些不同的View了。这里定义SackOfViewAdapter类,继承BaseAdapter,在该类中定义容器变量mViewList来存储ListView中不同列表项的view;同时,定义两个构造函数,一个是在参数中指定容器的大小,并填充null值;一个则直接传入ListView列表项中所有view的集合。代码如下:

SackOfViewAdapter类的关键代码在newView函数和getView函数,其中newView函数用于给容器变量mViewList中值为null的元素赋值,一般由SackOfViewAdapter的子类实现。而getView函数重写自BaseAdapter类,是Adapter返回View类实例的关键函数,代码如下所示:

SackOfViewAdapter类的完整代码如下所示:
- public class SackOfViewsAdapter extends BaseAdapter {
- private List<View> mViewList = null;
- /**
- * 构造大小为count,值为null的view集合,这时需要子类重写newView函数
- */
- public SackOfViewsAdapter(int count) {
- super();
- mViewList = new ArrayList<View>(count);
- for (int i = 0; i < count; i++) {
- mViewList.add(null);
- }
- }
- /**
- * 由传入的view集合直接给容器赋值,如果view集合中有为null值的view,则子类必须实现newView函数
- */
- public SackOfViewsAdapter(List<View> views) {
- super();
- this.mViewList = views;
- }
- /**
- * 返回对应位置的列表项
- */
- @Override
- public Object getItem(int position) {
- return mViewList.get(position);
- }
- /**
- * 返回列表项的个数
- */
- @Override
- public int getCount() {
- return mViewList.size();
- }
- /**
- * getView函数创建的列表项类型个数
- */
- @Override
- public int getViewTypeCount() {
- return getCount();
- }
- /**
- * getView函数创建的view类型值,这里以view所在的位置作为类型值
- */
- @Override
- public int getItemViewType(int position) {
- return position;
- }
- /**
- * 如果Adapter中所有列表项都是可点击和可选择的,则返回true
- */
- @Override
- public boolean areAllItemsEnabled() {
- return false;
- }
- /**
- * 如果position所指的列表项不是分隔符,则返回true
- */
- @Override
- public boolean isEnabled(int position) {
- return false;
- }
- /**
- * 返回指定位置position的列表项的view
- */
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- View result = mViewList.get(position);
- // 如果mViewList中的view为null,则需要调用newView函数来创建一个,该函数由子类来实现
- if (result == null) {
- result = newView(position, parent);
- mViewList.set(position, result);
- }
- return result;
- }
- /**
- * 创建列表中指定位置的列表项,该函数有子类实现
- */
- protected View newView(int position, ViewGroup parent) {
- throw new RuntimeException("You must override newView()!");
- }
- /**
- * 获得指定位置的列表项的id
- */
- @Override
- public long getItemId(int position) {
- return position;
- }
- /**
- * 判断Adapter中是否存在某个指定的view
- */
- public boolean hasView(View v) {
- return mViewList.contains(v);
- }
- }
最后,以一个实例来说明SackOfViewAdapter类的使用方法,实例中我们定义4个不同布局的列表项,其中一个为null值,由SackOfViewAdapter的子类重写newView函数实现赋值,其他三个则不是null值。这四个view的布局文件分别是main_notify.xml、update_progress_notify.xml、notification_battery.xml和main_notify_red.xml,这些资源借用自360手机卫士,实例效果如下图所示:

而实例的代码如下:
- public class SackOfViewsDemo extends ListActivity {
- @Override
- public void onCreate(Bundle bundle) {
- super.onCreate(bundle);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.main);
- ArrayList<View> views = new ArrayList<View>();
- LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- // 列表项1
- View view = inflater.inflate(R.layout.main_notify, null);
- views.add(view);
- // 列表项2
- view = inflater.inflate(R.layout.update_progress_notify, null);
- views.add(view);
- // 列表项3
- view = inflater.inflate(R.layout.notification_battery, null);
- views.add(view);
- // 列表项4(为null值,在newView函数中创建)
- views.add(null);
- setListAdapter(new SillyAdapter(views));
- }
- class SillyAdapter extends SackOfViewsAdapter {
- public SillyAdapter(List<View> views) {
- super(views);
- }
- protected View newView(int position, ViewGroup parent) {
- LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = inflater.inflate(R.layout.main_notify_red, null);
- return view;
- }
- }
- }
本文的SackOfViewAdapter类参考自 https://github.com/commonsguy/cwac-sacklist
本文源码参见:http://download.csdn.net/detail/ace1985/4575749
Android开源代码解读-基于SackOfViewAdapter类实现类似状态通知栏的布局的更多相关文章
- Android开源代码解读のOnScrollListener实现ListView滚屏时不加载数据
使用ListView过程中,如果滚动加载数据的操作比较费时,很容易在滚屏时出现屏幕卡住的现象,一个解决的办法就是不要在滚动时加载数据,而是等到滚动停止后再进行数据的加载.这同样要实现OnScrollL ...
- material design 的android开源代码整理
material design 的android开源代码整理 1 android (material design 效果的代码库) 地址请点击:MaterialDesignLibrary 效果: 2 ...
- android开源代码
Android开源项目--分类汇总 转自:https://github.com/Trinea/android-open-project Android开源项目第一篇——个性化控件(View)篇 包括L ...
- 160多个android开源代码汇总
第一部分 个性化控件(View) 主要介绍那些不错个性化的View,包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.Pro ...
- 优秀开源代码解读之JS与iOS Native Code互调的优雅实现方案
简介 本篇为大家介绍一个优秀的开源小项目:WebViewJavascriptBridge. 它优雅地实现了在使用UIWebView时JS与ios 的ObjC nativecode之间的互调,支持消息发 ...
- Github上不错的Android开源代码(一)
总有一些朋友很热心的整理一些好的资料,在收集之后,可以用作阅读.学习和实践.小伙伴们,总有一天,你也能写出 Niubility 的 Android App :-) 为了防止以上链接失效,以及部分内容丢 ...
- Hybrid----优秀开源代码解读之JS与iOS Native Code互调的优雅实现方案-备
本篇为大家介绍一个优秀的开源小项目:WebViewJavascriptBridge. 它优雅地实现了在使用UIWebView时JS与ios 的ObjC nativecode之间的互调,支持消息发送.接 ...
- 22个值得收藏的Android开源代码-UI篇
本文介绍了android开发者中比较热门的开源代码,这些代码绝大多数可以直接应用到项目中. FileBrowserView 一个强大的文件选择控件.界面比较漂亮,使用也很简单.特点:可以自定义UI:支 ...
- 22个值得收藏的Android开源代码——cool
转自http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1020/1808.html 本文介绍了android开发者中比较热门的开源代 ...
随机推荐
- VS2012发布网站IIS配置
首先要配置好下面步骤 然后 把图上勾选的都勾选 最后一步 那IIS就配置好了,怎么添加发布呢打开IIS管理器 然后带点击网站添加网站 ,在这之前首先要在磁盘里新建一个文件夹,把项目复制过去,网站随便命 ...
- Android Log日志文件的分析、查看
Log 在android中的地位非常重要,要是作为一个android程序员不能过分析log这关,算是android没有入门吧 . 下面我们就来说说如何处理log文件 什么时候会产生log文件呢 ?一般 ...
- C#--virtual,abstract,override,new,sealed
virtual:使用此关键字,可以使其在派生类中被重写. abstract:抽象方法,由子类重写,或继续为抽象方法存在,并由其子子类实现. override: 重写父类方法,属性,或事件的抽象实现或虚 ...
- PartialView 加载Js
地址记录:http://stackoverflow.com/questions/21186505/including-script-specific-to-an-asp-net-mvc4-view-o ...
- C++ 知识点 2
基本类型常量 const int a; int const a; const int *a; int * const a; int const * a const; 之间的区别? const int ...
- Go语言之defer
defer语句被用于预定对一个函数的调用.我们把这类被defer语句调用的函数称为延迟函数.注意,defer语句只能出现在函数或方法的内部. 一条defer语句总是以关键字defer开始.在defer ...
- javascript之事件绑定
曾经写过一篇随笔,attachEvent和addEventListener,跟本文内容有很多相似之处 本文链接:javascript之事件绑定 1.原始写法 <div onclick=" ...
- UCOS 内存管理理解 创建任务
OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err) { ................... ...
- Activiti 使用自己的身份认证服务
Activiti 中内置了用户和组管理的服务,由identityService 提供调用接口,默认在spring配置中如下: <bean id="identityService&quo ...
- PYTHON线程知识再研习B
使用threading.Thread模块,也有两种使用方法,可以用类,也可以在实例化对象中传入函数或类实例. #!/usr/bin/env python # -*- coding: utf-8 -*- ...