Android—万能ListView适配器

吴泽乐 8年前
   <p>ListView是开发中最常用的控件了,但是总是会写重复的代码,浪费时间又没有意义。</p>    <p>最近参考一些资料,发现一个万能ListView适配器,代码量少,节省时间,总结一下分享给大家。</p>    <p>首先有一个自定义的Adapter继承于BaseAdapter,下面是自定义的Adapter,精华在getView()方法中</p>    <pre>  <code class="language-java">package com.example.mylistview.util;    import java.util.List;    import android.content.Context;  import android.view.LayoutInflater;  import android.view.View;  import android.view.ViewGroup;  import android.widget.BaseAdapter;    public abstract class CommonAdapter<T> extends BaseAdapter {      /**       * 上下文       */      private Context mContext;      /**       * 实体类集合       */      private List<T> mDatas;      private LayoutInflater mInflater;      /**       * 控件id       */      private int mlayoutId;        public CommonAdapter(Context context, List<T> datas, int layoutId) {          this.mContext = context;          this.mDatas = datas;          this.mlayoutId = layoutId;          mInflater = LayoutInflater.from(context);      }        @Override      public int getCount() {          // TODO Auto-generated method stub          return mDatas.size();      }        @Override      public T getItem(int arg0) {          // TODO Auto-generated method stub          return mDatas.get(arg0);      }        @Override      public long getItemId(int arg0) {          // TODO Auto-generated method stub          return arg0;      }        @Override      public View getView(int arg0, View arg1, ViewGroup arg2) {          // TODO Auto-generated method stub          ViewHolder holder = ViewHolder.get(mContext, arg1, arg2, mlayoutId,                  arg0);          convert(holder, getItem(arg0));            return holder.getConvertView();      }        public abstract void convert(ViewHolder holder, T t);  }  </code></pre>    <p>以上的抽象方法convert(ViewHolder holder, T t);就相当于以前通用代码中的</p>    <p>viewHolder.mTextView = (TextView) convertView .findViewById(R.id.id_tv_title);</p>    <p>viewHolder.mTextView.setText(Bean.getName());</p>    <p>找到控件的id再去设施setText等重复的代码方法中的参数ViewHolder holder, T t    holder就相当于以前通用代码中的viewHolder,t就相当于一个自己定义的实体类Bean。</p>    <p>以上代码中getView()方法中有一个ViewHolder是需要自己声明的,以下是代码以及详细注释:</p>    <pre>  <code class="language-java">package com.example.mylistview.util;    import android.content.Context;  import android.graphics.Bitmap;  import android.renderscript.Type;  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 {      /**       * SparseArray类存放View集合       */      private SparseArray<View> mViews;      /**       *        */      private int mPosition;      /**       * 布局文件       */      private View mConvertView;        public View getConvertView() {          return mConvertView;      }        public ViewHolder(Context context, ViewGroup parent, int layoutId,              int position) {          this.mViews = new SparseArray<View>();          this.mPosition = position;          this.mConvertView = LayoutInflater.from(context).inflate(layoutId,                  parent, false);          this.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 (null == convertView) {              return new ViewHolder(context, parent, layoutId, position);          } else {              ViewHolder holder = (ViewHolder) convertView.getTag();              holder.mPosition = position;              return holder;          }      }      /**       * 通过控件的id获取对应的控件,如果没有则加入views       * @param viewId       * @return       */      public <T extends View> T getView(int viewId) {          View view = mViews.get(viewId);            if (null == view) {              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 tv = getView(viewId);          tv.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;        }                public int getPosition()        {            return mPosition;        }    }  </code></pre>    <p>再写一个Adapter继承于万能适配器CommonAdapter,还是要写一个自己的Adapter,因为一个项目可能会有多个ListView,但是每个的item元素,布局都会有所不同的,这个泪用来区分不同的ListView与自己所对应的item.这个代码量较少完全可以写成内部类在Activity.java中.</p>    <pre>  <code class="language-java">package com.example.mylistview.adapter;    import java.util.List;    import android.content.Context;  import android.view.View;  import android.view.View.OnClickListener;  import android.widget.CheckBox;    import com.example.mylistview.R;  import com.example.mylistview.domain.Bean;  import com.example.mylistview.util.CommonAdapter;  import com.example.mylistview.util.ViewHolder;    public class MyAdapter extends CommonAdapter<Bean> {        public MyAdapter(Context context, List<Bean> datas, int layoutId) {          super(context, datas, layoutId);          // TODO Auto-generated constructor stub      }        @Override      public void convert(ViewHolder holder, final Bean bean) {          // TODO Auto-generated method stub          holder.setText(R.id.tv_title, bean.getTitle())                  .setText(R.id.tv_desc, bean.getDesc())                  .setText(R.id.tv_time, bean.getTime())                  .setText(R.id.tv_phone, bean.getPhone());          /**           * 防止CheckBox混乱           */          final CheckBox cBox = (CheckBox)(holder.getView(R.id.cb));          if (cBox != null)          {              cBox.setChecked(bean.isChecked());                cBox.setOnClickListener(new OnClickListener()              {                  @Override                  public void onClick(View v)                  {                      bean.setChecked(cBox.isChecked());                  }              });          }      }    }  </code></pre>    <p>优化之后用适配器的时候就简单多了下面是实体类,item和MainActivity.java中的代码:</p>    <p>实体类:</p>    <pre>  <code class="language-java">package com.example.mylistview.domain;    public class Bean {      private String title;      private String desc;      private String time;      private String phone;      private boolean isChecked;        public boolean isChecked() {          return isChecked;      }        public void setChecked(boolean isChecked) {          this.isChecked = isChecked;      }        /**       * @param title       * @param desc       * @param time       * @param phone       */      public Bean(String title, String desc, String time, String phone) {          this.title = title;          this.desc = desc;          this.time = time;          this.phone = phone;      }        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 getTime() {          return time;      }        public void setTime(String time) {          this.time = time;      }        public String getPhone() {          return phone;      }        public void setPhone(String phone) {          this.phone = phone;      }    }  </code></pre>    <p>MainActivity.java:</p>    <p>重点代码:</p>    <pre>  <code class="language-java">参数有上下文,集合,和自己对应的item就可以了</code></pre>    <pre>  <code class="language-java"> adapter = new MyAdapter(this, mDatas, R.layout.item);  </code></pre>    <pre>  <code class="language-java">package com.example.mylistview.ui;    import java.util.ArrayList;  import java.util.List;    import android.app.Activity;  import android.content.Intent;  import android.os.Bundle;  import android.view.View;  import android.widget.AdapterView;  import android.widget.AdapterView.OnItemClickListener;  import android.widget.ListView;    import com.example.mylistview.R;  import com.example.mylistview.adapter.MyAdapter;  import com.example.mylistview.domain.Bean;    public class MainActivity extends Activity {      private ListView listView;      private List<Bean> mDatas;      /**       * 适配器       */      private MyAdapter adapter;        @Override      protected void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_main);          initView();          initData();          listener();      }        private void listener() {          // TODO Auto-generated method stub          listView.setOnItemClickListener(new OnItemClickListener() {                @Override              public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,                      long arg3) {                  // TODO Auto-generated method stub                  startActivity(new Intent(MainActivity.this, SecondActivity.class));              }          });      }        private void initData() {          // TODO Auto-generated method stub          mDatas = new ArrayList<Bean>();          Bean bean = new Bean("Android新技能 Get",                  "Android-打造万能的ListView和GridView适配器", "2015-08-05", "10086");          mDatas.add(bean);          bean = new Bean("捡到权志龙一个",                  "在星巴克捡到权志龙一个", "2015-08-06", "10086");          mDatas.add(bean);          bean = new Bean("GetTOP一个",                  "在韩国首尔捡到TOP一个", "2015-08-07", "10086");          mDatas.add(bean);                adapter = new MyAdapter(this, mDatas, R.layout.item);          listView.setAdapter(adapter);                }        private void initView() {          // TODO Auto-generated method stub          listView = (ListView) findViewById(R.id.listView);      }    }  </code></pre>    <p>item布局:</p>    <pre>  <code class="language-java"><?xml version="1.0" encoding="utf-8"?>  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:padding="10dp" >        <CheckBox          android:focusable="false"          android:id="@+id/cb"          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:layout_alignParentRight="true"          android:layout_centerInParent="true" />        <TextView          android:id="@+id/tv_title"          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:layout_marginTop="10dp"          android:singleLine="true"          android:text="Android新技能 Get" />        <TextView          android:id="@+id/tv_desc"          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:layout_below="@id/tv_title"          android:layout_marginTop="10dp"          android:layout_toLeftOf="@id/cb"          android:maxLines="2"          android:text="Android-打造万能的ListView和GridView适配器"          android:textColor="#898989" />        <TextView          android:id="@+id/tv_time"          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:layout_below="@id/tv_desc"          android:layout_marginTop="10dp"          android:text="2015-08-05"          android:textColor="#898989"          android:textSize="12sp" />        <TextView          android:id="@+id/tv_phone"          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:layout_alignParentRight="true"          android:layout_below="@id/tv_desc"          android:layout_marginTop="10dp"          android:background="#20793D"          android:maxLines="1"          android:text="10086"          android:padding="4dp"          android:textColor="#FFF" />    </RelativeLayout>  </code></pre>    <p>效果图:</p>    <p><img src="https://simg.open-open.com/show/89593689838c5efe45bb4d7ce3098f3e.png"></p>    <p>用这个去适配另一个不同的布局:</p>    <p>新布局的Adapter一样继承自己的万能adapter:CommonAdapter</p>    <pre>  <code class="language-java">package com.example.mylistview.adapter;    import java.util.List;  import java.util.Map;      import android.content.Context;    import com.example.mylistview.R;  import com.example.mylistview.util.CommonAdapter;  import com.example.mylistview.util.ViewHolder;    public class SecondAdapter extends CommonAdapter<Map<String, String>> {        public SecondAdapter(Context context, List<Map<String, String>> datas,              int layoutId) {          super(context, datas, layoutId);          // TODO Auto-generated constructor stub      }        @Override      public void convert(ViewHolder holder, Map<String, String> t) {          // TODO Auto-generated method stub          holder.setText(R.id.tv_item2values, t.get("values"));      }    }  </code></pre>    <p>Activity.java代码:</p>    <pre>  <code class="language-java">package com.example.mylistview.ui;    import java.util.ArrayList;  import java.util.HashMap;  import java.util.List;  import java.util.Map;    import android.app.Activity;  import android.os.Bundle;  import android.widget.ListView;    import com.example.mylistview.R;  import com.example.mylistview.adapter.MyAdapter;  import com.example.mylistview.adapter.SecondAdapter;    public class SecondActivity extends Activity {      private ListView listView_second;      private SecondAdapter secondAdapter;      private List<Map<String, String>> lists = new ArrayList<Map<String, String>>();        @Override      protected void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_second);          initView();          initData();      }        private void initData() {          // TODO Auto-generated method stub          for (int i = 0; i < 4; i++) {              Map map = new HashMap<String, String>();              map.put("values", "条目" + i);              lists.add(map);          }          secondAdapter = new SecondAdapter(this, lists, R.layout.item2);          listView_second.setAdapter(secondAdapter);      }        private void initView() {          // TODO Auto-generated method stub          listView_second = (ListView) findViewById(R.id.listView_second);      }    }  </code></pre>    <p>item:</p>    <pre>  <code class="language-java"><?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"      android:orientation="horizontal" >             <TextView          android:id="@+id/tv_item2values"          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:layout_gravity="center"          android:text="ffffff"          android:layout_margin="16dp"          android:gravity="center" />    </LinearLayout>  </code></pre>    <p>效果图:</p>    <p><img src="https://simg.open-open.com/show/2d305cbee087d7db89acb28647428ba6.png"></p>    <p>备忘,希望能给大家带来帮助。</p>    <p> </p>    <p>来自:http://www.cnblogs.com/yunfang/p/5777014.html</p>    <p> </p>    <p><span style="background:rgb(189, 8, 28) url("data:image/svg+xml; border-radius:2px; border:medium none; color:rgb(255, 255, 255); cursor:pointer; display:none; font:bold 11px/20px "Helvetica Neue",Helvetica,sans-serif; opacity:1; padding:0px 4px 0px 0px; position:absolute; text-align:center; text-indent:20px; width:auto; z-index:8675309">Save</span></p>