Android ListView 加载空布局
2015-10-08 13:36
525 查看
原创性声明:本文系作者原创,转载请附原文地址:http://blog.csdn.net/a774057695/article/details/48971429
在上一篇文章中Android
ListView改变数据源,我们谈到了如何让ListView在数据源改变时处理的更加顺手,同时,我们遗留了一个问题,那就是没有数据时未能完成空布局的加载。
当时我试图从ListView入手,让listview加载一个空布局,然后发现,这比较难以实现,死磕代价太大,要把ListView大改。于是我想:为什么不做一个特殊的view,它具有不同的状态,不同状态时显示不同的布局呢。
所以,我们的题目显得有点标题党,显示空布局(以及其他状态的布局)的并不是listview,而是它的父容器。
因为公司会将它作为一个项目,并需要实现更多的功能,所以这里我不方便开放源码。
该部分我打包成了库,大家可以使用它,我将它上传到了csdn,下载地址,下面展示一下使用方法:
我定义了四种状态:
正常状态
意外状态
等待状态
数据为空状态(初始化时默认)
这四种状态会对应四种布局:
正常状态显示listview
其他三种状态使用用户自定义的布局,并且可以自定义其事件,需要注意的是,请在该布局最外层额外套一层布局容器,以保护布局。
切换状态的API:
ChangeToLoading()
显示等待状态视图
ChangeToRetry()
显示出错状态视图,请注意,何为出错请自行定义,例如加载网络数据超时时可以显示该布局,网络访问超时被定义为出错
ChangeToNormal()
显示正常状态视图
ChangeToEmpty()
显示数据源为空状态视图,作者注:用于增强交互友好感,是否有实际需求请结合情况自行斟酌
设置非正常状态视图的函数原型:
void SetLoadingView(View v)
或者 void SetLoadingView(int id)
设置等待状态的视图
void SetRetryView(View v)
或者void SetRetryView(int id)
设置出错状态的视图
void SetEmptyView(View v)
或者void SetEmptyView(int id)
设置空数据时的视图
出于某些原因,在Activity的onDestroy中调用
Release()方法以实现某些功能组件的释放。
布局代码中添加组件:
activity中声明实例并实例化:
listview的item布局可以自定义
listview的适配器请继承SuperListViewAdapter,并实现必要的方法,它看起来和继承baseadapter的类差不多,只是进行了更多的扩展
牵涉到数据变化的方法重写时请调用notifyDataSetChanged();这些是上一篇的内容了。
注意:设置适配器时,注意方法为:mListView.SetAdapter(mListAdapter);
这里给出demo中的一些文件:可以和上一篇对比阅读。
适配器类:
至此,我们将上一篇中遗留的问题解决了。
本文系作者原创,转载请附原文地址:http://blog.csdn.net/a774057695/article/details/48971429
在上一篇文章中Android
ListView改变数据源,我们谈到了如何让ListView在数据源改变时处理的更加顺手,同时,我们遗留了一个问题,那就是没有数据时未能完成空布局的加载。
当时我试图从ListView入手,让listview加载一个空布局,然后发现,这比较难以实现,死磕代价太大,要把ListView大改。于是我想:为什么不做一个特殊的view,它具有不同的状态,不同状态时显示不同的布局呢。
所以,我们的题目显得有点标题党,显示空布局(以及其他状态的布局)的并不是listview,而是它的父容器。
因为公司会将它作为一个项目,并需要实现更多的功能,所以这里我不方便开放源码。
该部分我打包成了库,大家可以使用它,我将它上传到了csdn,下载地址,下面展示一下使用方法:
我定义了四种状态:
正常状态
意外状态
等待状态
数据为空状态(初始化时默认)
这四种状态会对应四种布局:
正常状态显示listview
其他三种状态使用用户自定义的布局,并且可以自定义其事件,需要注意的是,请在该布局最外层额外套一层布局容器,以保护布局。
切换状态的API:
ChangeToLoading()
显示等待状态视图
ChangeToRetry()
显示出错状态视图,请注意,何为出错请自行定义,例如加载网络数据超时时可以显示该布局,网络访问超时被定义为出错
ChangeToNormal()
显示正常状态视图
ChangeToEmpty()
显示数据源为空状态视图,作者注:用于增强交互友好感,是否有实际需求请结合情况自行斟酌
设置非正常状态视图的函数原型:
void SetLoadingView(View v)
或者 void SetLoadingView(int id)
设置等待状态的视图
void SetRetryView(View v)
或者void SetRetryView(int id)
设置出错状态的视图
void SetEmptyView(View v)
或者void SetEmptyView(int id)
设置空数据时的视图
出于某些原因,在Activity的onDestroy中调用
Release()方法以实现某些功能组件的释放。
布局代码中添加组件:
<individual.leobert.superlistview.SuperListView android:layout_width="match_parent" android:layout_height="match_parent"> </individual.leobert.superlistview.SuperListView>
activity中声明实例并实例化:
private SuperListView mListView = null; mListView =(SuperListView) findViewById(R.id.XXXXXXXXX);
listview的item布局可以自定义
listview的适配器请继承SuperListViewAdapter,并实现必要的方法,它看起来和继承baseadapter的类差不多,只是进行了更多的扩展
牵涉到数据变化的方法重写时请调用notifyDataSetChanged();这些是上一篇的内容了。
注意:设置适配器时,注意方法为:mListView.SetAdapter(mListAdapter);
这里给出demo中的一些文件:可以和上一篇对比阅读。
public class MainActivity extends Activity implements OnClickListener { private SuperListView mListView = null; private testAdapter mListAdapter = null; private LinkedList<MyData> mData = null; private Context mContext = null; //==========\ 测试数据 /=============================== /** * 我们假定添加到第五条,位置应该是4,我们的位置和数据源一致,从0 开始,不考虑偏移值 * */ private final int testPosition = 4; private MyData testData ; private int testDataId = 0; //==========\ 测试数据定义结束 /========================================== //=========\测试按钮 /========================================= private Button tBAdd,tBAddAt,tBDeleteAt,tBDeleteAll; private final String Tag = "MainActivity"; private Button Inview; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContext = this; BindView(); mData = new LinkedList<MyData>(); mListAdapter = new testAdapter(mData,mContext); mListView.SetAdapter(mListAdapter); // testAddAll(); // // testReplaceAll(); Inview = (Button) findViewById(R.id.bt); Inview.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { testAddAll(); } }); } private void testReplaceAll() { GetData(3); mListAdapter.ReplaceAll(mData); } private void testAddAll() { GetData(5); mListAdapter.AddAll(mData); } private void GetData(int count) { mData = new LinkedList<MyData>(); for (int i = 0; i < count; i++) { testData = new MyData(R.drawable.ic_launcher, "testAddAllData,id:" + i); mData.add(testData); } } private void BindView() { mListView =(SuperListView) findViewById(R.id.main_list); tBAdd = (Button) findViewById(R.id.bt_addAtLast); tBAddAt = (Button) findViewById(R.id.bt_addAtPosition); tBDeleteAt = (Button) findViewById(R.id.bt_deleteAtPosition); tBDeleteAll = (Button) findViewById(R.id.bt_deleteAll); tBAdd.setOnClickListener(this); tBAddAt.setOnClickListener(this); tBDeleteAll.setOnClickListener(this); tBDeleteAt.setOnClickListener(this); // mListView.SetEmptyView(LayoutInflater.from(mContext).inflate(R.layout.nodata,null,true)); mListView.SetEmptyView(R.layout.nodata); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } @Override public void onClick(View v) { // TODO Auto-generated method stub boolean op = true; StringBuffer msg = new StringBuffer(); testData = new MyData(R.drawable.ic_launcher, "testData,id:"+(testDataId++)); boolean ret = false; switch (v.getId()) { case R.id.bt_addAtLast: ret = mListAdapter.AddItem(testData); msg.append("从尾部添加,成功了吗?").append(ret); break; case R.id.bt_addAtPosition: ret = mListAdapter.AddItem(testPosition, testData); msg.append("添加到第5条,成功了吗?").append(ret); break; case R.id.bt_deleteAtPosition: ret = mListAdapter.DeleteItem(testPosition); msg.append("删除第5条,成功了吗?").append(ret); break; case R.id.bt_deleteAll: mListAdapter.Clear(); msg.append("全部清除"); break; default: op = false; break; } mListView.ChangeToNormal(); if(op) { Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show(); Log.i(Tag, msg.toString()); } } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); mListView.Release(); } }
适配器类:
public class testAdapter extends SuperListViewAdapter{ private Context mContext; // 依据原楼主的代码,我们定义自己的数据类型,使用类来描述 private LinkedList<MyData> mLiData; public testAdapter(LinkedList<MyData> mData, Context mContext) { super(mContext); this.mLiData = mData; this.mContext = mContext; } private class ViewHolder { ImageView mImageView; TextView mTextView; } @Override public int getCount() { return mLiData.size(); } /* * 这里我返回数据源中的值。 */ @Override public Object getItem(int position) { return mLiData.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; Log.i("adapter","getView"); if (convertView == null) { convertView = LayoutInflater.from(mContext).inflate( R.layout.listview_item, parent, false); holder = new ViewHolder(); holder.mImageView = (ImageView) convertView .findViewById(R.id.img_icon); holder.mTextView = (TextView) convertView .findViewById(R.id.txt_content); convertView.setTag(holder); }else{ holder = (ViewHolder) convertView.getTag(); } holder.mImageView.setImageResource(mLiData.get(position).getImgId()); holder.mTextView.setText(mLiData.get(position).getContent()); return convertView; } //=======================================================================// /* * 以下是实现接口定义的方法 * * 定义为Boolean 返回类型 是为了方便通知“前台”,成功了没有, * 注意 我们的position按照数据来,从0开始,当然你看着自己需求指定偏移量也可以 * * (⊙﹏⊙)b 我打着插入。。。想想还是改成了添加。。。感觉自己病了 */ //=======================================================================// @Override public boolean AddItem(Object data) { if (mLiData == null) mLiData = new LinkedList<MyData>(); mLiData.add((MyData) data); notifyDataSetChanged(); return true; } @Override public boolean AddItem(int position , Object data) { if (mLiData == null) mLiData = new LinkedList<MyData>(); //注意超过了数据源的实际条目数时,需要的是添加到尾部,而不是直接添加,更不是在中间补充空值 //当然,你也可以认为必须朝该位置插入,不能满足时通知前台要求不被许可,不执行。 我的例子中就采用这样处理 if (position > getCount()) // AddItem(data); //这里对应调整向朝尾部添加 return false; else mLiData.add(position,(MyData) data); notifyDataSetChanged(); return true; } @Override public boolean DeleteItem(int position) { if (mLiData == null) return false; if (position >= getCount()) return false; mLiData.remove(position); notifyDataSetChanged(); return true; } public void Clear() { if (mLiData == null) mLiData = new LinkedList<MyData>(); mLiData.clear(); notifyDataSetChanged(); } @SuppressWarnings("unchecked") @Override public void AddAll(Object datas) { if (mLiData == null) mLiData = new LinkedList<MyData>(); for(int i = 0;i<((LinkedList<MyData>) datas).size();i++) { mLiData.add(((LinkedList<MyData>) datas).get(i)); } notifyDataSetChanged(); } @SuppressWarnings("unchecked") @Override public void ReplaceAll(Object datas) { mLiData = new LinkedList<MyData>(); for(int i = 0;i<((LinkedList<MyData>) datas).size();i++) { mLiData.add(((LinkedList<MyData>) datas).get(i)); } notifyDataSetChanged(); } }
至此,我们将上一篇中遗留的问题解决了。
本文系作者原创,转载请附原文地址:http://blog.csdn.net/a774057695/article/details/48971429
相关文章推荐
- Android的一些错误集合!
- 实用的AndroidStudio快捷键
- Android 图像处理(浮雕、复古、怀旧等)
- android-打包安装过程
- Android多线程(三)
- Android权限问题整理 非常全面
- android 短信数据库 结构
- android与html交互
- Android:简单的开场界面
- Android动画自定义解析
- Android第三方支付——Bmob支付总结
- android实现状态栏添加图标的函数实例
- 【转】Android布局优化之ViewStub
- 【转】Android布局优化之ViewStub
- Android 使用 9.png 为 background 时 产生位移
- Android 信息获取
- android实现添加耳机状态图标的方法
- 安卓切换Activity时的动画效果
- Android进阶之大话设计模式
- IOS,ANDROID,.NET通用AES加密算法