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

前言

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可以实现事件回调,自定义回调更好用;

源码连接

# 转载请注明出处!!!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值