关于为android的ViewGroup加上适配器的一些看法..
来源:互联网 发布:歌词创作软件 - 百度 编辑:程序博客网 时间:2024/05/14 09:43
先不说别的, 上图:
项目中,我们可能会遇到以上那种情况 ,
颜色,品牌,尺寸,等规格,每个规格里面有长短不一,大小不一,数量不一的规格项,如果用GridView,则每一项的个数, 都会固定,实现不了这种错落排版的效果。
怎么办?
怎么办?
怎么办?
于是在github上逛了一圈, 找到了我想要的:
https://github.com/blazsolar/FlowLayout ,
感谢前人们为我们提供的方便
到这里,还没有结束, 下面才是今天要讨论的东西。
这个FlowLayout,一般用法是addView(view),可是,我还要嵌套在一个listview里面,要在getView里面每次
for(xx : xx) { View view = View.inflate(xxxx,xxx,xx); Xx xx = view.findViewById(R.id.xx) Xx xx = ....; xx.setText(xx); ...}
好可怕 。
怎么办?
android已经给我们提供指导方向了, 所以我们在使用ListView,GridView等等多条目控件的时候,会写一个适配器,把数据层给分开,那这个能加一个适配器吗,ok,老思路先分析 :
1.首先我要给FlowLayout加个setAdapter(ListAdapter adapter);2.数据变动我要改动Flowlayout里面的view,看看ListView源码,要给adapter注册一个Observer,类似这样:adapter.registerDataSetObserver(new DataSetObserver() { @Override public void onChanged() { changeViews(); } @Override public void onInvalidated() { changeViews(); } });实现这个之后,在adapter的notifyDatasetChange的时候,onChanged方法就会回调3.利用adapter的getView来得到赋值好的view,并加到FlowLayout,4.能不能考虑下复用view,不能每次removeAllViews()再addView啊。
好了,分析完了,从第一条开始上代码:
private ListAdapter adapter; public void setAdapter(@NonNull ListAdapter adapter) { if (adapter == null) throw new NullPointerException("FlowLayout.setAdapter不能传空参数"); this.adapter = adapter; changeViews(); //这个是用来给Flowlayout加view的逻辑,先忽略 adapter.registerDataSetObserver(new DataSetObserver() { @Override public void onChanged() { changeViews(); } @Override public void onInvalidated() { changeViews(); } }); }
代码很简单,
1.就是在FlowLayout里面保留一个adapter,
2.然后从adapter里面询问view,
3.注册观察对象,得以在adapter.notifyDataSetChanged()的时候,能感知到。
本身很简单,一共就两个方法嘛~
下面贴changeViews()方法:
private void changeViews() { final int count = adapter.getCount(); if (count > 0) { int childCount = getChildCount(); if (childCount > count) { removeViews(count, childCount - count); } for (int i = 0; i < count; i++) { final View view = adapter.getView(i, getChildAt(i), this); if (view.getLayoutParams() == null) { LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); lp.rightMargin = childHorizontal; lp.bottomMargin = childVerticle; view.setLayoutParams(lp); } if(getChildAt(i) != view) { addView(view); } } }else{ removeAllViews(); } }
这里稍微麻烦点,
为什么呢?因为考虑到我们不能每一次都让adapter重新创建新view,这样实则是一种性能上的浪费,但是真做到ListView那种级别的复用,也是难。所以,我就简单点做,能复用就复用,不能复用再创建。
"能复用就复用,不能复用再创建" 怎么体现出来的呢?final int count = adapter.getCount(); //先拿到要显示的view的数量 if (count > 0) { //在即将显示的数量大于0的情况下 再lookup一下flowlayout当前子view的数量 int childCount = getChildCount(); if (childCount > count) { //如果说flowlayout当前的子view数量多过要显示的view数量,那就删除几个,让其数量保持一致 removeViews(count, childCount - count); }//上面就是我所说的‘能复用就复用,不能复用再创建‘for (int i = 0; i < count; i++) {//这个就比较简单了, 向adapter要view。//getChildAt(i) 就是adapter内getView中的第二个参数 convertView,//如果有就传过去 ,没有就是null,这时按正常来说,我们会重新创建一个view。 final View view = adapter.getView(i, getChildAt(i), this); if (view.getLayoutParams() == null) {//好了,这时呢得到了一个view,看看有没有 布局参数,//没有就给一个,免得FlowLayout自动生成一个的话//会match_parent,这样就不合我们的要求了, LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);//这些就是加加右和下margin,让view 不会粘一起,好看一点,//可以做成一个自定义属性嘛,从xml里面读,这个就不讨论了, lp.rightMargin = childHorizontal; lp.bottomMargin = childVerticle; view.setLayoutParams(lp); } if(getChildAt(i) != view) {//这里,为啥要判断下呢?//这要说到前面的蹩脚的复用了,//前面把getChildAt(i)传给了getView,如果FlowLayout本身就有view,//那么在getView里面,就只是改变一下text,image等等的数据,这时//getChildAt(i) 和adater返回的view肯定还是同一个view,所以不用重复加//----//但是如果不一样,那就是说,getChildAt(i)就是null , 跟本就没有, addView(view); } }
ok,FlowLayout的改造已经完工了,
回到第一张图上去,看看怎么用的吧
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:padding="@dimen/dp10" android:background="#fff" android:orientation="vertical"> <TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="42dp" android:gravity="center_vertical" android:textColor="@color/normalText" android:textSize="@dimen/normal" /> <demo.FlowLayout android:id="@+id/flowLayout" android:layout_marginTop="@dimen/dp10" app:childHorizontal="5dp" app:childVerticle="5dp" android:layout_width="match_parent" android:layout_height="wrap_content"/></LinearLayout>
public class SelectGuigeAdapter extends LBaseAdapter<GuigeBean, SelectGuigeAdapter.VH> { public SelectGuigeAdapter(Context context) { super(context); } @Override public VH createViewHolder(ViewGroup parent, int position) { return new VH(View.inflate(getContext(),R.layout.select_guige_list_item,null)); } @Override public void bindViewHolder(VH holder, GuigeBean data, int position) { holder.txtTitle.setText(data.name); //这里显示的是颜色,品牌等 holder.mAdapter.setDataSource(data.items, true); //这里是具体的规格项 } static class VH extends LBaseAdapter.ViewHolder { private TextView txtTitle; private FlowLayout flowLayout; private SelectGuigeItemAdapter mAdapter; public VH(View convertView) { super(convertView); txtTitle = get(R.id.title); flowLayout = get(R.id.flowLayout); if (mAdapter == null) { mAdapter = new SelectGuigeItemAdapter(getContext()); flowLayout.setAdapter(mAdapter); } } }}
再看FlowLayout的适配器
public class SelectGuigeItemAdapter extends LBaseAdapter<String, LBaseAdapter.ViewHolder> { public SparseBooleanArray selectMap = new SparseBooleanArray(); public SelectGuigeItemAdapter(Context context) { super(context); } @Override public ViewHolder createViewHolder(ViewGroup parent, int position) { return new ViewHolder(View.inflate(getContext(), R.layout.checkedtextview_item,null)); } @Override public void bindViewHolder(ViewHolder holder, String data, final int position) { CheckedTextView txt = holder.get(R.id.text); txt.setText(data); txt.setChecked(selectMap.get(position,false)); txt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { selectMap.clear(); selectMap.put(position, true); notifyDataSetChanged(); } }); }}
ok,连起来了, 这个LBaseAdapter是什么鬼, 大家可以关注下我的上一遍文章
关于android中listview的adapter如何通用的一些看法
嗯,先到这,写的不好,望指正
- 关于为android的ViewGroup加上适配器的一些看法..
- android关于ViewGroup的一些事一些情
- 关于技术支持的一些看法
- 关于领导艺术的一些看法
- 关于论文答辩的一些看法
- 关于程序设计语言的一些看法
- 关于Keil 的一些看法
- 关于程序语言的一些看法
- 关于CSDN的一些看法
- 关于C++的一些看法
- 关于OpenStack的一些看法
- 关于Bootloader的一些看法
- 关于equals的一些看法
- 关于dubbo的一些看法
- 关于Appdelegate 的一些看法
- 关于WifiManager的一些看法
- 关于流的一些看法
- Android关于自定义ViewGroup,onMeasure的一些实验结论。
- Android最新技术学习笔记
- 关于angular瀑布流插件ng-infinite-scroll.min.js遇到一个奇葩问题
- Nutch的Hadoop方式爬取效率优化
- 父元素与子元素之间的margin-top问题
- LTE终端开机流程----同步和小区驻留
- 关于为android的ViewGroup加上适配器的一些看法..
- 设计思路JAVA斗地主
- 删除studio额外项目,module
- 网易视频云:Maven入门学习教程(下)
- VB Val和CDbl的区别
- python 整体输出字典中的中文
- 颜色处理
- IOS 如何通过浏览器打开App
- 最简单的WebRTC示例