zoukankan      html  css  js  c++  java
  • android打造万能的适配器

    荒废了两天,今天与大家分享一个ListView的适配器

    前段时间在学习慕课网的视频,觉得这种实现方式较好,便记录了下来,最近的项目中也使用了多次,节省了大量的代码,特此拿来与大家分享一下。

    还是先看图片,这里我模仿博客园App的列表样式做了一个静态的数据列表

      

    这里用到的类比较多,不过核心的只有两个,其余均为演示所用,先来看核心的两个类

    ViewHolderM.java

    package landptf.tools;
    
    import android.content.Context;
    import android.text.Spanned;
    import android.util.SparseArray;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    /**
     * @author landptf
     * 公共的ViewHolder
     */
    public class ViewHolderM {
        private SparseArray<View> viewArray;
        private int position;
        private View mConvertView;
        private Object tag;
    
        /** 
         * 构造方法
         * @param context
         * @param convertView
         * @param parent
         * @param layoutId
         * @param position
         */
        public ViewHolderM(Context context, View convertView, ViewGroup parent,
                int layoutId, int position) {
            this.position = position;
            //使用SparseArray效率高一些
            viewArray = new SparseArray<View>();
            //加载布局
            mConvertView = LayoutInflater.from(context).inflate(layoutId, parent,false);
            //将ViewHolderM赋值给View的Tag
            mConvertView.setTag(this);
        }
    
        public static ViewHolderM get(Context context, View convertView,
                ViewGroup parent, int layoutId, int position) {
            if (convertView == null) {
                //如果convertView为空,则实例化ViewHolderM
                return new ViewHolderM(context, convertView, parent, layoutId,position);
            } else {
                //否则从convertView的Tag中取出ViewHolderM,避免重复创建 
                ViewHolderM holder = (ViewHolderM) convertView.getTag();
                holder.position = position;
                return holder;
            }
        }
    
        public View getConvertView() {
            return mConvertView;
        }
    
        public Object getTag() {
            return tag;
        }
    
        public void setTag(Object tag) {
            this.tag = tag;
        }
        
        public int getPosition() {
            return position;
        }
    
        public void setPosition(int position) {
            this.position = position;
        }
    
        /**
         * 通过viewId获取控件对象
         * @param viewId
         * @return
         */
        @SuppressWarnings("unchecked")
        public <T extends View> T getView(int viewId) {
            View view = viewArray.get(viewId);
            if (view == null) {
                view = mConvertView.findViewById(viewId);
                viewArray.put(viewId, view);
            }
            return (T) view;
        }
        
        
        /**------------------------------------华丽的分割线------------------------------------*/
        /**以下方法为额外封装的方法,只是简单几个,以后可以慢慢完善*/
        
        
        /**
         * 设置TextView的内容
         * @param viewId
         * @param text
         * @return
         */
        public ViewHolderM setText(int viewId, String text) {
            TextView tv = getView(viewId);
            tv.setText(text);
            return this;
        }
        
        /**
         * 设置TextView的内容
         * @param viewId
         * @param text,Spanned类型,可设置部分字体变色
         * @return
         */
        public ViewHolderM setText(int viewId, Spanned text) {
            TextView tv = getView(viewId);
            tv.setText(text);
            return this;
        }
        
        /**
         * 设置图片的可见性
         * @param viewId
         * @param visible
         * @return
         */
        public ViewHolderM setImageViewVisible(int viewId, Boolean visible){
            ImageView iv = getView(viewId);
            if (visible) {
                iv.setVisibility(View.VISIBLE);
            }else {
                iv.setVisibility(View.GONE);
            }
            return this;
        }
    }

    2 AdapterM.java

    package landptf.tools;
    
    import java.util.List;
    
    import android.content.Context;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    
    /**
     * @author landptf
     * 公共的Adapter List适配器
     */
    public abstract class AdapterM<T> extends BaseAdapter {
    
        private Context context;
        //为丰富程序功能,提供了两种常见的数据类型
        private List<T> dataList = null;//数据源List<T>
        private T[] dataArray = null;//数据源T[]
        //布局文件ID
        private int layoutId;
        
        /**
         * 构造方法
         * @param context
         * @param layoutId
         * @param dataList
         */
        public AdapterM(Context context,int layoutId, List<T> dataList) {
            this.context = context;
            this.dataList = dataList;
            this.layoutId = layoutId;
        }
        
        /**
         * 构造方法(与上一个只有数据源不同)
         * @param context
         * @param layoutId
         * @param dataArray
         */
        public AdapterM(Context context,int layoutId, T[] dataArray) {
            this.context = context;
            this.dataArray = dataArray;
            this.layoutId = layoutId;
        }
        
        @Override
        public int getCount() {
            if (dataList != null) {
                return dataList.size();
            }else {
                return dataArray.length;
            }
        }
        @Override
        public T getItem(int position) {
            if (dataList != null) {
                return dataList.get(position);
            }else {
                return dataArray[position];
            }
            
        }
        @Override
        public long getItemId(int position) {
            return position;
        }
        
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolderM holder = new ViewHolderM(context, convertView, parent,layoutId, position);
            convert(holder,getItem(position));
            return holder.getConvertView();
        }
        /**
         * 需实现的抽象方法
         * @param holder
         * @param model
         */
        public abstract void convert(ViewHolderM holder, T model);
    }

    接下来看布局文件,一共两个一个是activity的页面,一个列表项
    activity_list.xml

    <?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="match_parent"
        android:background="#EFEFEF" >
        
         <include android:id="@+id/title" layout="@layout/child_titlebarm" />
         
         <ListView 
             android:id="@+id/lv_list"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_below="@+id/title"
             android:layout_marginTop="10dp"
             android:background="@android:color/white"
             android:divider="#A9A9A9"  
            android:dividerHeight="1dp">
         </ListView>
    
    </RelativeLayout>

    item_messgae.xml

    <?xml version="1.0" encoding="utf-8"?>
    <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="wrap_content"
        tools:ignore="HardcodedText" >
    
        <TextView
            android:id="@+id/tv_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginTop="10dp"
            android:maxLines="2"
            android:textColor="#696969"
            android:textSize="20sp" />
    
        <TextView
            android:id="@+id/tv_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/tv_title"
            android:layout_below="@+id/tv_title"
            android:layout_marginRight="10dp"
            android:layout_marginTop="10dp"
            android:maxLines="3"
            android:textColor="#696969"
            android:textSize="16sp" />
    
        <TextView
            android:id="@+id/tv_comment"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/tv_content"
            android:layout_below="@+id/tv_content"
            android:layout_marginTop="10dp"
            android:textColor="#696969"
            android:textSize="18sp" />
    
        <TextView
            android:id="@+id/tv_read"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignTop="@+id/tv_comment"
            android:layout_centerHorizontal="true"
            android:textColor="#696969"
            android:textSize="18sp" />
    
        <TextView
            android:id="@+id/tv_collect"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignTop="@+id/tv_read"
            android:layout_alignParentRight="true"
            android:layout_marginRight="10dp"
            android:text="立马收藏"
            android:textColor="#696969"
            android:textSize="18sp" />
    
    </RelativeLayout>

    接下来我们定义了一个Adapter类继承AdapterM,ListAdapter.java

    package landptf.test;
    
    import landptf.control.R;
    import android.content.Context;
    import landptf.tools.AdapterM;
    import landptf.tools.ViewHolderM;
    
    /**
     * @author landptf
     * ListAdapter List适配器
     */
    public class ListAdapter extends AdapterM<MessageBean>{
    
        public ListAdapter(Context context, int layoutId, MessageBean[] dataArray) {
            super(context, layoutId, dataArray);
        }
    
        @Override
        public void convert(ViewHolderM holder, MessageBean model) {
            // 为个控件绑定内容
            holder.setText(R.id.tv_title, model.getTitle());
            holder.setText(R.id.tv_content, model.getContent());
            holder.setText(R.id.tv_comment, model.getComment() + "条评论");
            holder.setText(R.id.tv_read, model.getRead() + "阅读");
        }
    }

    最后是Activity类,ListActivity.java

    package landptf.test;
    
    import landptf.control.R;
    import landptf.control.TitleBarM;
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.ListView;
    
    /**
     * @author landptf
     * List适配器测试类
     */
    public class ListActivity extends Activity{
        //这里用到了之前的自定义标题栏
        //如果感兴趣可以看一下我的上一篇博客,否则忽略即可 
        private TitleBarM tbTitle;
        //ListView对象
        private ListView lvList;
        //自定义Adapter
        private ListAdapter listAdapter;
        //数据源实体,这里用数组作为示例,大家也可以选择使用List作为数据源
        private MessageBean[] msgArray;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_list);
            initView();
        }
    
        private void initView() {
            tbTitle = (TitleBarM) findViewById(R.id.tbm_title);
            tbTitle.setTitleText("打造万能的适配器");
            initData();
            lvList = (ListView) findViewById(R.id.lv_list);
            listAdapter = new ListAdapter(this, R.layout.item_message, msgArray);
            lvList.setAdapter(listAdapter);
        }
    
        //装载数据
        private void initData() {
            msgArray = new MessageBean[10];
            msgArray[0] = new MessageBean("Android 自定义标题栏", "今天来看一下如何通过组合多个控件实现自定义标题栏众所周知,标题栏是应用中必不可少的控件,为了避免多次重写,将其封装起来,供每个布局调用即可。这里我们采用经典的左中右布局,也可以根据项目需要自行调整,比如在右侧再加一个控件,或者将标题偏左都可以注:其中应用到了上一篇文章中的ButtonM控件,大家可以", 0, 273);
            msgArray[1] = new MessageBean("android自定义控件,动态设置Button样式", "今天来看一个通过重写Button来动态实现一些效果,如圆角矩形、圆形、按下改变字体,改变背景色,改变背景图等在此说明一下,这种实现方式绝对不是唯一的,而且通过xml文件即可简单实现,这样做只是为了将控件的样式完全由代码实现,更方便打包应用于其他项目下面来看几张效果图: 图1 初始状态 图2 按下第一", 0, 400);
            msgArray[2] = new MessageBean("Android 自定义控件实现TextView按下后字体颜色改变", "今天跟大家分享一下Android自定义控件入门,先介绍一个简单的效果TextView,按下改变字体颜色,后期慢慢扩展更强大的功能直接看图片 第一张是按下后截的图,功能很简单,也很容易实现,下面来看一下如何通过重写TextView来实现一共三个文件 TextViewM.java,MainActivit", 0, 202);
            msgArray[3] = new MessageBean("Android 自定义标题栏", "今天来看一下如何通过组合多个控件实现自定义标题栏众所周知,标题栏是应用中必不可少的控件,为了避免多次重写,将其封装起来,供每个布局调用即可。这里我们采用经典的左中右布局,也可以根据项目需要自行调整,比如在右侧再加一个控件,或者将标题偏左都可以注:其中应用到了上一篇文章中的ButtonM控件,大家可以", 0, 273);
            msgArray[4] = new MessageBean("android自定义控件,动态设置Button样式", "今天来看一个通过重写Button来动态实现一些效果,如圆角矩形、圆形、按下改变字体,改变背景色,改变背景图等在此说明一下,这种实现方式绝对不是唯一的,而且通过xml文件即可简单实现,这样做只是为了将控件的样式完全由代码实现,更方便打包应用于其他项目下面来看几张效果图: 图1 初始状态 图2 按下第一", 0, 400);
            msgArray[5] = new MessageBean("Android 自定义控件实现TextView按下后字体颜色改变", "今天跟大家分享一下Android自定义控件入门,先介绍一个简单的效果TextView,按下改变字体颜色,后期慢慢扩展更强大的功能直接看图片 第一张是按下后截的图,功能很简单,也很容易实现,下面来看一下如何通过重写TextView来实现一共三个文件 TextViewM.java,MainActivit", 0, 202);
            msgArray[6] = new MessageBean("Android 自定义标题栏", "今天来看一下如何通过组合多个控件实现自定义标题栏众所周知,标题栏是应用中必不可少的控件,为了避免多次重写,将其封装起来,供每个布局调用即可。这里我们采用经典的左中右布局,也可以根据项目需要自行调整,比如在右侧再加一个控件,或者将标题偏左都可以注:其中应用到了上一篇文章中的ButtonM控件,大家可以", 0, 273);
            msgArray[7] = new MessageBean("android自定义控件,动态设置Button样式", "今天来看一个通过重写Button来动态实现一些效果,如圆角矩形、圆形、按下改变字体,改变背景色,改变背景图等在此说明一下,这种实现方式绝对不是唯一的,而且通过xml文件即可简单实现,这样做只是为了将控件的样式完全由代码实现,更方便打包应用于其他项目下面来看几张效果图: 图1 初始状态 图2 按下第一", 0, 400);
            msgArray[8] = new MessageBean("Android 自定义控件实现TextView按下后字体颜色改变", "今天跟大家分享一下Android自定义控件入门,先介绍一个简单的效果TextView,按下改变字体颜色,后期慢慢扩展更强大的功能直接看图片 第一张是按下后截的图,功能很简单,也很容易实现,下面来看一下如何通过重写TextView来实现一共三个文件 TextViewM.java,MainActivit", 0, 202);
            msgArray[9] = new MessageBean("Android 自定义标题栏", "今天来看一下如何通过组合多个控件实现自定义标题栏众所周知,标题栏是应用中必不可少的控件,为了避免多次重写,将其封装起来,供每个布局调用即可。这里我们采用经典的左中右布局,也可以根据项目需要自行调整,比如在右侧再加一个控件,或者将标题偏左都可以注:其中应用到了上一篇文章中的ButtonM控件,大家可以", 0, 273);
        }
    }

    以上便是全部代码,这样以后再新增其他ListView都不需要再定义一个Adapter,一个ViewHolder,上面的ListAdapter也可以不需要,直接在Activity里实现定义AdapterM即可,但是一些复杂的列表项还是建议自定义一个Adapter去继承AdapterM.

    最后本着互联网开放、分享的精神,将原视频地址附上http://www.imooc.com/learn/372,个人比较喜欢慕课网。

  • 相关阅读:
    iOS之UITableView的上拉刷新
    iOS xml文件的解析方式 XMLDictionary,GDataXMLNode,NSXMLParser
    iOS学习基本常识
    iOS常用宏定义
    iOS查错机制
    轻量级sqlite是增删改查
    iOS开发UI篇—ios应用数据存储方式(归档) :转发
    iOS面向对象的建模:MVC(OC基础)
    iOS下bound,center和frame
    CSS----学习2
  • 原文地址:https://www.cnblogs.com/landptf/p/4579554.html
Copyright © 2011-2022 走看看