自定义万能Adapter和自定义多变布局可交互ListView(一)

来源:互联网 发布:电磁炉 电陶炉 知乎 编辑:程序博客网 时间:2024/06/07 05:29

前言

ListView与Adapter是Android一组很常用的组合,本篇博客旨在探究它们的各种应用场景:1、自定义万用Adapter+自定义同布局不可交互ListView(简单)2、自定义万用Adapter+自定义不同布局可交互ListView(略复杂)

自定义万能用Adapter

一、准备内容:

    1.自定义ViewHolder;    2.自定义Abstract CommonAdapter(extends BaseAdapter)    3.自定义Entity用于存储数据(复杂情况下可以对多种数据类型进行封装)    4.自定义回调接口或抽象类

二、CommonAdapter需要数据:

    1.Context context;--上下文不要解释    2.List<Entity>;--Entity里可封装多种数据类型

三、CommonAdapter提供调用方法(不包含BaseAdapter的抽象方法):

    1.abstract void convert;--获取item组件的抽象方法,子类继承实现    2.abstract int getLayoutId;--获取item布局的抽象方法,子类继承实现,可用于获取不同布局

四、自定义ViewHolder提供给CommonAdapter的调用方法

    1.getViewHolder;--获取ViewHolder实例    2.getmContertView;--返回已加载ContertView实例    3.getView;--获取item内组件

五、子类XXXAdapterCommonAdapter

    1.实现抽象方法;    2.设置回调onXXXListener;

六、演示效果

这里写图片描述

七、直接贴代码

    1.FirstListActivity:        (1)activity_firstlist:            <?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:id="@+id/activity_main"                android:layout_width="match_parent"                android:layout_height="match_parent"                android:paddingBottom="@dimen/activity_vertical_margin"                android:paddingLeft="@dimen/activity_horizontal_margin"                android:paddingRight="@dimen/activity_horizontal_margin"                android:paddingTop="@dimen/activity_vertical_margin"                tools:context="heros.example.com.mylistview.MainActivity">                <TextView                    android:id="@+id/textView"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_centerHorizontal="true"                    android:textSize="20dp"                    android:text="自定义万能用Adapter" />                <ListView                    android:id="@+id/firstlist"                    android:layout_marginTop="20dp"                    android:layout_below="@+id/textView"                    android:layout_width="match_parent"                    android:layout_height="match_parent">                </ListView>            </RelativeLayout>        (2)FirstListActivity.class            public class FirstListActivity extends AppCompatActivity {                List<MyEntity> entityList;                MyEntity firstEntity;                FirstAdapter mAdapter;                @BindView(R.id.firstlist)                ListView firstlist;                @Override                protected void onCreate(Bundle savedInstanceState) {                    super.onCreate(savedInstanceState);                    setContentView(R.layout.activity_firstlist);                    ButterKnife.bind(this);                    setItem();                }                private void setItem() {                    //构造数据                    entityList = new ArrayList<MyEntity>();//空指针高发处                    for (int i=0; i < 20; i++) {                        firstEntity = new MyEntity(R.layout.item_fistlist,R.drawable.book,                                "神经网络与深度学习","电子工业出版社","价格:¥"+(40+i));                        entityList.add(firstEntity);                    }                    //创建adapter                    mAdapter = new FirstAdapter(this,entityList, mClickListener, onItemClickListener);                    firstlist.setAdapter(mAdapter);                    //设置回调                    firstlist.setOnItemClickListener(onItemClickListener);                }                //Item响应回调                AdapterView.OnItemClickListener onItemClickListener = new AdapterView.OnItemClickListener() {                    @Override                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {                        Toast.makeText(FirstListActivity.this, "这一本:¥" + (40+position),                                Toast.LENGTH_SHORT).show();                    }                };                //控件响应回调                MyClickListener mClickListener = new MyClickListener() {                    @Override                    public void myOnClick(int position, View view) {                        Toast.makeText(FirstListActivity.this, "这一本是:神经网络与深度学习",                                Toast.LENGTH_SHORT).show();                    }                    public void onClick(View v) {   //先响应onclick(权限高) 可以将响应移交出去                        myOnClick((Integer) v.getTag(), v);                    }                };            }    2.自定义适配器        (1)FirstAdapter.class继承自CommonAdapter.class                public class FirstAdapter extends CommonAdapter {                //这里声明了两种回调响应                //OnItemClickListenerListView自带属性                AdapterView.OnItemClickListener onItemClickListener;                //MyClickListener自定义响应接口(也可使用抽象类回调)                MyClickListener mClickListener;                public FirstAdapter(Context context, List<MyEntity> list, MyClickListener myClickListener,                                     AdapterView.OnItemClickListener onItemClickListener) {                    //回调父类构造方法                    super(context, list);                    this.onItemClickListener = onItemClickListener;                    this.mClickListener = myClickListener;                }                //实现父类抽象方法,加载item内组件                @Override                public void convert(ViewHolder mViewHolder, MyEntity mEntity, int position) {                    ImageView leftImg = (ImageView) mViewHolder.getView(R.id.leftImg);                    TextView tv1 = (TextView) mViewHolder.getView(R.id.itemTv1);                    TextView tv2 = (TextView) mViewHolder.getView(R.id.itemTv2);                    TextView tv3 = (TextView) mViewHolder.getView(R.id.itemTv3);                    leftImg.setImageResource(mEntity.getImgId());                    tv1.setText(mEntity.getNameStr());                    tv2.setText(mEntity.getIntroduceStr());                    tv3.setText(mEntity.getPirceStr());                    leftImg.setOnClickListener(mClickListener);                }                //实现父类抽象方法,传送item布局id                @Override                public int getLayoutId(int type) {                    return R.layout.item_fistlist;                }            }        (2)抽象类CommomAdapetr.class            public abstract class CommonAdapter extends BaseAdapter {            ViewHolder mViewHolder;            List<MyEntity> mEntityList;            MyEntity mEntity;            LayoutInflater mInflater;            Context context;            public CommonAdapter(Context context, List<MyEntity> list){                this.context = context;                this.mEntityList = list;                mInflater = LayoutInflater.from(context);            }            @Override            public int getCount() {                return mEntityList.size();            }            //这里主要返回的类型修改为MyEntity            @Override            public MyEntity getItem(int position) {                return mEntityList.get(position);            }            @Override            public long getItemId(int position) {                return position;            }            @Override            public View getView(int position, View convertView, ViewGroup parent) {                //从MyEntity中获取布局类型号,调用子类实现抽象方法getLayoutId,获取布局int                int layoutId = getLayoutId(getItem(position).getType());                //获取mViewHolder实例                ViewHolder mViewHolder = getViewHolder(context,position,convertView,parent,layoutId);                convert(mViewHolder,getItem(position),position);                //一定注意这里返回的方式,我就遗忘这里不止一次造成空指针                return mViewHolder.getContertView();            }            //获取item组件的抽象方法,子类继承实现            public abstract void convert(ViewHolder mViewHolder, MyEntity mEntity, int position);            //获取item布局的抽象方法,子类继承实现,可用于获取不同布局            public abstract int getLayoutId(int type);        }        (3)ViewHolder.class(也可以写成内部类)            public class ViewHolder {                private SparseArray<View> mView;//存储要获取组件的数组                private int position;                private View mContertView;//装载组件的容器                public ViewHolder(Context context,int position,ViewGroup parent,int layoutId){                    this.position = position;                    this.mView = new SparseArray<View>();                    mContertView = LayoutInflater.from(context).inflate(layoutId,parent,false);                    mContertView.setTag(this);                }                public static ViewHolder getViewHolder(Context context,int position, View convertView, ViewGroup parent,int layoutId){                    //判断是否首次调用getViewHolder                    if(convertView==null){                        //首次为空                        return new ViewHolder(context,position,parent,layoutId);                    }else{                        //非首次不为空                        return (ViewHolder) convertView.getTag();                    }                }                //获取item内组件                public <T extends View> T getView(int viedId){                    View view = mView.get(viedId);                    if(view==null){                        view = mContertView.findViewById(viedId);                        mView.put(viedId,view);                    }                    return (T)view;                }                //返回已加载mContertView实例                public View getContertView(){                    return mContertView;                }            }    3.自定义数据存储与回调接口        (1)MyEntity.class            public class MyEntity{                public MyEntity(int type, int imgId, String nameStr, String introduceStr, String pirceStr) {                    this.type = type;                    this.imgId = imgId;                    this.nameStr = nameStr;                    this.introduceStr = introduceStr;                    this.pirceStr = pirceStr;                }                int type;                int imgId;                String nameStr;                String introduceStr;                String pirceStr;                public int getType() {                    return type;                }                public void setType(int type) {                    this.type = type;                }                public String getNameStr() {                    return nameStr;                }                public void setNameStr(String nameStr) {                    this.nameStr = nameStr;                }                public int getImgId() {                    return imgId;                }                public void setImgId(int imgId) {                    this.imgId = imgId;                }                public String getIntroduceStr() {                    return introduceStr;                }                public void setIntroduceStr(String introduceStr) {                    this.introduceStr = introduceStr;                }                public String getPirceStr() {                    return pirceStr;                }                public void setPirceStr(String pirceStr) {                    this.pirceStr = pirceStr;                }                public String toString(){                    String str = "MyEntity{type:"+Integer.toString(type)+",nameStr:"+nameStr+                            ",introduceStr"+introduceStr+",pirceStr:"+pirceStr+"}";                    return str;                }            }        (2)MyClickListener.class            public interface MyClickListener extends View.OnClickListener {                public void myOnClick(int position, View view);            }    4.程序入口MainActivity        (1)activity_main            <?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:id="@+id/activity_main"                android:layout_width="match_parent"                android:layout_height="match_parent"                android:paddingBottom="@dimen/activity_vertical_margin"                android:paddingLeft="@dimen/activity_horizontal_margin"                android:paddingRight="@dimen/activity_horizontal_margin"                android:paddingTop="@dimen/activity_vertical_margin"                tools:context="heros.example.com.mylistview.MainActivity">                <TextView                    android:id="@+id/textView"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_centerHorizontal="true"                    android:textSize="20dp"                    android:text="自定义ListView应用场景探究" />                <Button                    android:id="@+id/button1"                    android:text="自定义万用Adapter"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_below="@+id/textView"                    android:layout_alignLeft="@+id/textView"                    android:layout_alignRight="@+id/textView"                    android:layout_centerHorizontal="true"                    android:layout_marginTop="20dp"/>                <Button                    android:id="@+id/button2"                    android:text="自定义不同布局可交互ListView"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_below="@+id/button1"                    android:layout_alignLeft="@+id/textView"                    android:layout_alignRight="@+id/textView"                    android:layout_centerHorizontal="true"                    android:layout_marginTop="20dp"/>            </RelativeLayout>        (2)MainActivity.class            public class MainActivity extends AppCompatActivity {                @BindView(R.id.textView)                TextView textView;                @BindView(R.id.button1)                Button button1;                @BindView(R.id.button2)                Button button2;                @Override                protected void onCreate(Bundle savedInstanceState) {                    super.onCreate(savedInstanceState);                    setContentView(R.layout.activity_main);                    ButterKnife.bind(this);                }                @OnClick({R.id.button1, R.id.button2})                public void onClick(View view) {                    switch (view.getId()) {                        case R.id.button1:                            Intent i1 = new Intent(MainActivity.this,FirstListActivity.class);                            startActivity(i1);                            break;                        case R.id.button2:                            Intent i2 = new Intent(MainActivity.this,SecondListActivity.class);                            startActivity(i2);                            break;                    }                }            }

总结

1.通过abstract CommonAdapter + ViewHolder,仅仅需要FirstAdatper extends CommonAdapter,实现其中两个抽象方法就可以完成基础的adapter功能;

2.使用Entity可以传送多类型数据,并且可以通过设置type实现不同item布局;

3.使用XXXListener可以实现事件回调,自定义回调更好用;

源码连接

# 转载请注明出处!!!

原创粉丝点击