Android万能适配器Adapter
2015-08-22 21:06
573 查看
万能适配器的代码的github地址是https://github.com/fengsehng/CommonAdapter
欢迎大家补充
我们经常要书写Adapter,但是Adapter里面的重复代码很多,所以我们可以复用一下 ,只要是ViewHolder的部分和Adapter的部分
常用的继承BaseAdapter的Adapter的代码如下
package com.example.euler_kalvinhe.myadapter.adapter; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.example.euler_kalvinhe.myadapter.R; import com.example.euler_kalvinhe.myadapter.bean.Bean; import java.util.List; /** * Created by Euler-KalvinHe on 2015/8/20. */ public class MyAdapter extends BaseAdapter{ private LayoutInflater inflater; private List<Bean> listData; public MyAdapter(Context context,List<Bean> list) { inflater = LayoutInflater.from(context); this.listData = list; } @Override public int getCount() { return listData.size(); } @Override public Object getItem(int i) { return listData.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(int i, View view, ViewGroup viewGroup) { ViewHolder holder; if (view == null){ view = inflater.inflate(R.layout.item,viewGroup,false); holder = new ViewHolder(); holder.title = (TextView) view.findViewById(R.id.title); holder.desc = (TextView) view.findViewById(R.id.desc); holder.time = (TextView) view.findViewById(R.id.time); holder.phone = (TextView) view.findViewById(R.id.phone); view.setTag(holder); } else { holder = (ViewHolder) view.getTag(); } Bean bean = listData.get(i); holder.title.setText(bean.getTitle()); holder.desc.setText(bean.getDesc()); holder.time.setText(bean.getTime()); holder.phone.setText(bean.getPhone()); return view; } private class ViewHolder{ TextView title; TextView desc; TextView time; TextView phone; } }
对ViewHolder进行进行抽取,主要是初始化布局,判断ConvertView是否已经建立 ,注意重用Viewholder的时候position的设置,代码如下
package com.example.euler_kalvinhe.myadapter.utility; import android.content.Context; import android.graphics.Bitmap; import android.util.SparseArray; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; public class ViewHolder { private final SparseArray<View> mViews; private int mPosition; private View mConvertView; private ViewHolder(Context context, ViewGroup parent, int layoutId, int position) { this.mPosition = position; this.mViews = new SparseArray<View>(); mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false); // setTag mConvertView.setTag(this); } /** * 拿到一个ViewHolder对象 * * @param context * @param convertView * @param parent * @param layoutId * @param position * @return */ public static ViewHolder get(Context context, View convertView, ViewGroup parent, int layoutId, int position) { if (convertView == null) { return new ViewHolder(context, parent, layoutId, position); } return (ViewHolder) convertView.getTag(); } public View getConvertView() { return mConvertView; } /** * 通过控件的Id获取对于的控件,如果没有则加入views * * @param viewId * @return */ public <T extends View> T getView(int viewId) { View view = mViews.get(viewId); if (view == null) { view = mConvertView.findViewById(viewId); mViews.put(viewId, view); } return (T) view; } /** * 为TextView设置字符串 * * @param viewId * @param text * @return */ public ViewHolder setText(int viewId, String text) { TextView view = getView(viewId); view.setText(text); return this; } /** * 为ImageView设置图片 * * @param viewId * @param drawableId * @return */ public ViewHolder setImageResource(int viewId, int drawableId) { ImageView view = getView(viewId); view.setImageResource(drawableId); return this; } /** * 为ImageView设置图片 * * @param viewId * @param drawableId * @return */ public ViewHolder setImageBitmap(int viewId, Bitmap bm) { ImageView view = getView(viewId); view.setImageBitmap(bm); return this; } public int getPosition() { return mPosition; } }
Adapter类的抽取,主要是利用泛型实现了BaseAdapter的抽象方法
package com.example.euler_kalvinhe.myadapter.utility; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import java.util.List; public abstract class CommenAdapter<T> extends BaseAdapter { protected LayoutInflater mInflater; protected Context mContext; protected List<T> mDatas; protected final int mItemLayoutId; public CommenAdapter(Context context, List<T> mDatas, int itemLayoutId) { this.mContext = context; this.mInflater = LayoutInflater.from(mContext); this.mDatas = mDatas; this.mItemLayoutId = itemLayoutId; } @Override public int getCount() { return mDatas.size(); } @Override public T getItem(int position) { return mDatas.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { final ViewHolder viewHolder = getViewHolder(position, convertView, parent); convert(viewHolder, getItem(position)); return viewHolder.getConvertView(); } public abstract void convert(ViewHolder helper, T item); private ViewHolder getViewHolder(int position, View convertView, ViewGroup parent) { return ViewHolder.get(mContext, convertView, parent, mItemLayoutId, position); } }
activity的代码.匿名实现了Adapter
package com.example.euler_kalvinhe.myadapter; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.CheckBox; import android.widget.ListView; import android.widget.TextView; import com.example.euler_kalvinhe.myadapter.bean.Bean; import com.example.euler_kalvinhe.myadapter.utility.CommenAdapter; import com.example.euler_kalvinhe.myadapter.utility.ViewHolder; import java.util.ArrayList; import java.util.List; public class MainActivity extends Activity { private ListView listView; private List<Bean> listData = new ArrayList<Bean>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews(); initData(); listView.setAdapter(new CommenAdapter<Bean>(MainActivity.this,listData,R.layout.item) { @Override public void convert(ViewHolder holder, final Bean bean) { ((TextView)holder.getView(R.id.title)).setText(bean.getTitle()); ((TextView)holder.getView(R.id.desc)).setText(bean.getDesc()); ((TextView)holder.getView(R.id.time)).setText(bean.getTime()); ((TextView)holder.getView(R.id.phone)).setText(bean.getPhone()); final CheckBox checkBox = holder.getView(R.id.checkbox); checkBox.setChecked(bean.isChecked()); checkBox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { bean.setChecked(checkBox.isChecked()); } }); } }); } private void initData() { Bean bean = new Bean("android新技能","打造万能的adapter和Viewholder","201304","10086"); listData.add(bean); Bean bean1 = new Bean("android新技能1","打造万能的adapter和Viewholder","201304","10086"); listData.add(bean1); Bean bean2 = new Bean("android新技能2","打造万能的adapter和Viewholder","201304","10086"); listData.add(bean2); Bean bean3 = new Bean("android新技能3","打造万能的adapter和Viewholder","201304","10086"); listData.add(bean3); Bean bean4 = new Bean("android新技能4","打造万能的adapter和Viewholder","201304","10086"); listData.add(bean4); Bean bean5 = new Bean("android新技能5","打造万能的adapter和Viewholder","201304","10086"); listData.add(bean5); Bean bean6 = new Bean("android新技能6","打造万能的adapter和Viewholder","201304","10086"); listData.add(bean6); Bean bean7 = new Bean("android新技能7","打造万能的adapter和Viewholder","201304","10086"); listData.add(bean7); Bean bean8 = new Bean("android新技能8","打造万能的adapter和Viewholder","201304","10086"); listData.add(bean8); Bean bean9 = new Bean("android新技能9","打造万能的adapter和Viewholder","201304","10086"); listData.add(bean9); Bean bean10 = new Bean("android新技能10","打造万能的adapter和Viewholder","201304","10086"); listData.add(bean10); Bean bean11= new Bean("android新技能11","打造万能的adapter和Viewholder","201304","10086"); listData.add(bean11); } private void initViews() { listView = (ListView) findViewById(R.id.listView); } }
Bean是数据类,初始化了变量
package com.example.euler_kalvinhe.myadapter.bean; /** * Created by Euler-KalvinHe on 2015/8/20. */ public class Bean { private String title; private String desc; private String phone; private String time; private boolean isChecked; public Bean(String title, String desc, String time, String phone) { this.desc = desc; this.phone = phone; this.time = time; this.title = title; } public boolean isChecked() { return isChecked; } public void setChecked(boolean isChecked) { this.isChecked = isChecked; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getTime() { return time; } public void setTime(String time) { this.time = time; } }
布局类主要是主布局.包含ListView和item的布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="match_parent"></ListView> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:descendantFocusability="blocksDescendants"> <!--android:focusable="false"--> <CheckBox android:id="@+id/checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" /> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#888" android:text="android新技能" android:textSize="16sp" /> <TextView android:id="@+id/desc" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="打造万能的adapter和Viewholder" android:minLines="1" android:maxLines="2" android:layout_toLeftOf="@id/checkbox" android:layout_below="@id/title" android:layout_marginTop="10dp" android:textColor="#444" android:textSize="16sp"/> <TextView android:id="@+id/time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="201304" android:layout_below="@id/desc" android:layout_marginTop="10dp" android:textColor="#444" android:textSize="12sp"/> <TextView android:id="@+id/phone" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="10086" android:layout_below="@id/time" android:layout_marginTop="10dp" android:drawableLeft="@drawable/ic_action_phone_start" android:drawablePadding="5dp" android:padding="3dp" android:textColor="#fff" android:textSize="12sp" android:layout_alignParentRight="true" android:background="#ff2447ff"/> </RelativeLayout>
效果图
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!要注意的两个问题
1.第一个item中加入了CheckBox,CheckBox会抢焦点,使得勾选自己有效,然而点击整个item无效,这个问题,可以通过在item的根布局RelativeLayout里面加一句 android:descendantFocusability=”blocksDescendants”
2.第二个问题就是由于ViewHolder的复用导致,勾选前面的CheckBox,后面的自动勾选,解决办法是在Bean加入一个表示CheckBox是否勾选的布尔变量isChecked,具体如下
Bean里面
private boolean isChecked; ublic boolean isChecked() { return isChecked; } public void setChecked(boolean isChecked) { this.isChecked = isChecked; }
activity里面
final CheckBox checkBox = holder.getView(R.id.checkbox); checkBox.setChecked(bean.isChecked()); checkBox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { bean.setChecked(checkBox.isChecked()); } });
万能适配器的代码的github地址是https://github.com/fengsehng/CommonAdapter
我的文章首发于公众号 互联网学术(IT-paper) 了解更多,互请扫码上车
相关文章推荐
- php设计模式 Adapter(适配器模式)
- ListView Adapter优化 实例
- Adapter实现ListView带多选框等状态的自定义控件的注意事项
- 自定义Adapter并通过布局泵LayoutInflater抓取layout模板编辑每一个item实现思路
- Android中的Adapter简单介绍
- ASP.NET的适配器设计模式(Adapter)应用详解
- ListView的Adapter使用(绑定数据) 之 自定义每一项的布局去绑定数据
- android开发中ListView与Adapter使用要点介绍
- ListView的Adapter使用 之 初学ArrayAdapter String
- Generic adapter class in Python
- Android AdapterView 源码分析以及其相关回收机制的分析
- 有关ListView的三种适配器类型
- 从应用框架角度看ListView与Adapter类别
- Android之Adapter用法总结
- 记录讲解Android Adapter的一篇文章
- Adapter之BaseAdapter使用
- Java设计模式 结构模式-适配器模式(Adapter)
- ListView 和 Adapter 的基础
- Android 之 adapter.notifyDataSetChanged() 无响应
- BaseAdapter的使用