Android—万能ListView适配器

ListView是开发中最常用的控件了,但是总是会写重复的代码,浪费时间又没有意义。

最近参考一些资料,发现一个万能ListView适配器,代码量少,节省时间,总结一下分享给大家。

首先有一个自定义的Adapter继承于BaseAdapter,下面是自定义的Adapter,精华在getView()方法中

复制代码
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);
}
复制代码

以上的抽象方法convert(ViewHolder holder, T t);就相当于以前通用代码中的

viewHolder.mTextView = (TextView) convertView .findViewById(R.id.id_tv_title);

viewHolder.mTextView.setText(Bean.getName());

找到控件的id再去设施setText等重复的代码方法中的参数ViewHolder holder, T t    holder就相当于以前通用代码中的viewHolder,t就相当于一个自己定义的实体类Bean。

以上代码中getView()方法中有一个ViewHolder是需要自己声明的,以下是代码以及详细注释:

复制代码
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;  
    }  
}
复制代码

再写一个Adapter继承于万能适配器CommonAdapter,还是要写一个自己的Adapter,因为一个项目可能会有多个ListView,但是每个的item元素,布局都会有所不同的,这个泪用来区分不同的ListView与自己所对应的item.这个代码量较少完全可以写成内部类在Activity.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());
                }
            });
        }
    }

}
复制代码

 

优化之后用适配器的时候就简单多了下面是实体类,item和MainActivity.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;
    }

}
复制代码

MainActivity.java:

重点代码:

参数有上下文,集合,和自己对应的item就可以了
 adapter = new MyAdapter(this, mDatas, R.layout.item); 
复制代码
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);
    }

}
复制代码

item布局:

复制代码
<?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>
复制代码

效果图:

用这个去适配另一个不同的布局:

新布局的Adapter一样继承自己的万能adapter:CommonAdapter

复制代码
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"));
    }

}
复制代码

Activity.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);
    }

}
复制代码

item:

复制代码
<?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>
复制代码

效果图:

备忘,希望能给大家带来帮助。

posted @ 2016-08-17 14:40  KingWang588  阅读(279)  评论(0编辑  收藏  举报