Android进阶——RecycleView的使用之自定义单选列表(二)

引言

上一篇文章Android进阶——初识万能的RecycleView(一)介绍了下RecycleView的一些知识,以及组成成员所承担的角色和大致的原理流程,接下来就在实际应用中的一起体会吧,先放项目中的效果图直观感受下再一步步的去实现。(单击勾选同时动态获取设备的状态显示并获得对应的时间值,再次单击取消勾选,长按删除,单击自定义时弹出自定义对话框,选择时间之后显示到列表上)

一、实现的核心思想

很明显如果从UI方面去动态改变的话,不是不行,但是很麻烦,而我们知道RecycleView只是提供了一个容器,界面呈现的效果从一定程度来说只是取决于RecycleView.Adapter里创建了什么样的ViewHolder以及填充什么样的数据,所以要实现这个效果只需要考虑去动态更新RecycleView.Adapter,动态去绘制ItemView即可,剩下的逻辑就放在Activity去处理。

二、编码实现

1、使用RecycleView前得先在Android studio里对应的module模块下的gradle脚本引入

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.jakewharton:butterknife:7.0.1'
    compile 'com.android.support:appcompat-v7:24.2.0'
    compile 'com.android.support:recyclerview-v7:24.0.0'
}

2、编写RecycleView里item的布局文件和MainActivity的布局文件

RecycleView里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="wrap_content" android:orientation="vertical">
    <!--DevDelayActivity 选择时间列表的item-->
    <RelativeLayout  android:id="@+id/rl_choose_time" android:layout_width="match_parent" android:layout_height="60dp" android:orientation="horizontal" android:padding="6dp">

        <TextView  android:id="@+id/tv_delay_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:text="5分钟" android:textColor="@color/black" />

        <TextView  android:id="@+id/tv_dev_state" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginRight="33dp" android:layout_toLeftOf="@+id/iv_check" android:text="后开启" />

        <ImageView  android:id="@+id/iv_check" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" />

    </RelativeLayout>
</LinearLayout>

MainActivity的布局:

<?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:padding="10dp">

    <android.support.v7.widget.RecyclerView  android:id="@+id/listv_main" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="6dp" android:background="@drawable/shape_listv_bcg" >
    </android.support.v7.widget.RecyclerView>
</LinearLayout>

3、编写RecycleView的Adapter

实现Adapter可以分为几步:

  • 新建自己的Adapter类继承自RecyclerView.Adapter《RecyclerView.ViewHolder》 ,根据自己的业务封装对应的Bean
  • 实现onCreateViewHolder方法,这个方法的主要作用就是创建初始化对应的ViewHolder,与AdapterView的Adapter中的getView方法类似,但仅仅是创建ViewHolder并未开始填充数据绘制
  • 实现getItemCount返回数据集的size
  • 定义自己的ViewHolder 继承自 RecyclerView.ViewHolder,用于缓存item,可以通过弱引用来减少OOM
  • 定义Item的接口事件对应的回调接口
package crazymo.train.recycleview.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

import butterknife.Bind;
import butterknife.ButterKnife;
import crazymo.train.recycleview.R;
import crazymo.train.recycleview.bean.MainListItem;

/** * @auther: Crazy.Mo * Date: 2016/9/29 * Time:14:36 * Des:MainListView 的Adapter */
public class MainAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private List<MainListItem> mList = new ArrayList<>();
    private LayoutInflater mLayoutInflater;
    private static MainRecycleViewClickListener mListener;
    private Context mContext;

    public MainAdapter(Context context) {
        this.mContext = context;
        this.mLayoutInflater = LayoutInflater.from(context);
    }

    public void setList(List<MainListItem> list) {
        mList.clear();
        this.mList = list;
        notifyDataSetChanged();
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        MainViewHolder viewHolder = new MainViewHolder(mLayoutInflater.inflate(R.layout.listv_item_main, parent, false));
        viewHolder.setDelayAdapter(this);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ((MainViewHolder) holder).tvDelayTime.setText(mList.get(position).getTime());
        ((MainViewHolder) holder).tvDevState.setText(mList.get(position).getStateName());
        //根据check值动态创建对应的item
        if (mList.get(position).getIsCheck() == 1) {
            ((MainViewHolder) holder).ivCheck.setVisibility(View.VISIBLE);
            ((MainViewHolder) holder).ivCheck.setBackgroundResource(R.mipmap.selected_icon);
        } else {
            ((MainViewHolder) holder).ivCheck.setVisibility(View.INVISIBLE);
            ((DelayViewHolder) holder).ivCheck.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                if(mListener!=null){
                    v.setBackgroundResource(R.mipmap.selected_icon);
                }
            }
        }); 
    }

    @Override
    public int getItemViewType(int position) {
        return super.getItemViewType(position);
    }

    @Override
    public int getItemCount() {
        return mList.size();
    }

    class MainViewHolder extends RecyclerView.ViewHolder {

        @Bind(R.id.tv_delay_time)
        TextView tvDelayTime;
        @Bind(R.id.tv_dev_state)
        TextView tvDevState;
        @Bind(R.id.iv_check)
        ImageView ivCheck;

        private WeakReference<MainAdapter> ref;
        private MainAdapter mainAdapter;

        MainViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //执行Item Click事件
                    mListener.onItemClick(getLayoutPosition());
                }
            });
            itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    mListener.onItemLongClick(getLayoutPosition());
                    return true;//这里返回true 就不会在LongClick之后再重复执行onClick
                }
            });
        }

        public void setDelayAdapter(MainAdapter adapter) {
            if (adapter!=null){
                ref = new WeakReference<MainAdapter>(adapter);
            }
            mainAdapter = ref.get();
        }
    }
    //设置Item事件监听
    public void setOnMainRecycleOnClickListener(MainRecycleViewClickListener itemOnClickListener) {
        mListener = itemOnClickListener;
    }

    //定义Item事件接口
    public interface MainRecycleViewClickListener {
        void onItemClick(int pos);
        void onItemLongClick(int pos);
    }
}

package crazymo.train.recycleview.bean:

/** * @auther: Crazy.Mo * Date: 2016/9/29 * Time:14:23 * Des: */
public class MainListItem {
    private String time;
    private String stateName;
    private int isCheck;//0,未选中;1选中

    public MainListItem(String time, String stateName, int isCheck) {
        this.time = time;
        this.stateName = stateName;
        this.isCheck = isCheck;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getStateName() {
        return stateName;
    }

    public void setStateName(String stateName) {
        this.stateName = stateName;
    }

    public int getIsCheck() {
        return isCheck;
    }

    public void setIsCheck(int isCheck) {
        this.isCheck = isCheck;
    }
}

4、实现Activity

  • 实现RecycleView.Adapter的接口,用于接收处理Item事件
  • 在对应的生命周期方法中完成Adapter、RecycleView的初始化
  • 处理RecycleView.Adapter的事件,完成相关的业务逻辑
package crazymo.train.recycleview;

import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

import butterknife.Bind;
import butterknife.ButterKnife;
import crazymo.train.recycleview.adapter.DividerItemDecoration;
import crazymo.train.recycleview.adapter.MainAdapter;
import crazymo.train.recycleview.bean.MainListItem;

public class MainActivity extends Activity implements MainAdapter.MainRecycleViewClickListener{

    private static final String TAG ="CrazyMo" ;
    @Bind(R.id.listv_main)
    RecyclerView listvMain;
    private MainAdapter adapter;
    private List<MainListItem> list = new ArrayList<>();
    String deviceStatus="后开启";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        init();
    }
    private void init(){
        initRecycleView();
    }
    private void initRecycleView(){
        initListData();
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);//设置item垂直布局可以垂直滑动,也可设置为水平布局可以水平滑动
        adapter = new MainAdapter(this);
        if (adapter != null) {
            adapter.setList(list);
            adapter.setOnMainRecycleOnClickListener(this);
            listvMain.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));
            listvMain.setLayoutManager(layoutManager);
            listvMain.setHasFixedSize(true);
            listvMain.setAdapter(adapter);
        }
    }
    private void initListData(){
        list.add(new MainListItem("5分钟","",0));
        list.add(new MainListItem("10分钟","",0));
        list.add(new MainListItem("15分钟","",0));
        list.add(new MainListItem("20分钟","",0));
        list.add(new MainListItem("25分钟","",0));
        list.add(new MainListItem("30分钟","",0));
        list.add(new MainListItem("自定义","",0));
    }

    @Override
    public void onItemClick(int pos){
        for(int i=0;i<list.size();i++){
            //首先定位到需要修改数据项

            if(i==pos && pos!=6){
                if(list.get(pos).getIsCheck()==1){
                    list.get(pos).setIsCheck(0);
                    list.get(pos).setStateName("");
                }
                else {
                    list.get(pos).setIsCheck(1);
                    list.get(pos).setStateName(deviceStatus);
                }
            }
            else if(i==pos && pos==6){
                if(list.get(pos).getIsCheck()==1){
                    list.get(pos).setIsCheck(0);
                    list.get(pos).setTime("自定义");
                    list.get(pos).setStateName("");

                }else {
                    list.get(pos).setIsCheck(1);
                    list.get(pos).setStateName(deviceStatus);
                }
            }else{
                list.get(i).setIsCheck(0);
                list.get(i).setStateName("");
            }
        }
        adapter.notifyDataSetChanged();
        Log.e(TAG, "onItemClick: " );
    }

    @Override
    public void onItemLongClick(int pos) {
        //实现RecycleView的Item 长按击触发的方法
        list.remove(pos);
        adapter.notifyItemRangeRemoved(0,pos);
        Log.e(TAG, "onItemLongClick: " );
    }
}

运行结果(简化了很多效果,同时也为了突出显示分割线,故意做得这么不和谐)

Android进阶——RecycleView的使用之自定义单选列表(二)_第1张图片

你可能感兴趣的:(android,自定义view,RecyclView,单选列表,自定义勾选)