RecyclerView 通用 RecyclerAdapter 和通用 ViewHolder 封装

1. 概述

1.1 功能列表

  1. 类之间的关系简单, 两个类搞定(核心代码才几十行), 使用简单方便
  2. 同时支持单布局多布局
  3. 支持链式设置 item
  4. 支持 item 点击和长按事件
  5. RecyclerView、ListView 之类的 ViewHolder 都可以直接支持

1.2 使用方式

public class TestActivity extends BaseActivity {

    private final List<String> data = new ArrayList<>(100);
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_activity_layout);

        for (int i = 0; i < 100; i++) {
            data.add("text-" + i);
        }

        RecyclerView recyclerView = findViewById(R.id.recyclerview);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
//        recyclerView.setAdapter(getSimpleAdapter());    // 使用单布局
//        recyclerView.setAdapter(getSingleAdapter());    // 使用单布局
        recyclerView.setAdapter(getMultipleAdapter());    // 使用多布局
    }


    private RecyclerView.Adapter getSimpleAdapter() {
        return new SimpleAdapter<>(data, android.R.layout.simple_list_item_1, new SimpleAdapter.OnBindViewListener<String>() {

            @Override
            public void onBindView(ViewHolder holder, List<String> data, int position) {

                // 方式一 : 链式调用设置 ItemView
                holder.setText(android.R.id.text1, data.get(position))
                      .setTextColor(android.R.id.text1, Color.RED)
                      .setOnItemClickListener((view) ->
                          Toast.makeText(TestActivity.this, String.valueOf(position), Toast.LENGTH_SHORT).show()
                      );

                // 方式二 : 获取控件进行特殊设置(RecyclerHolder 中仅提供控件常用函数链式调用)
                if (position == 0) {
                    TextView textView = holder.getView(android.R.id.text1);
                    textView.setText(R.string.app_name, TextView.BufferType.NORMAL);
                }
            }
        });
    }


    private RecyclerView.Adapter getSingleAdapter() {
        return new MultipleAdapter<>(data, new MultipleAdapter.OnBindViewListener<String>() {

            @Override
            public int getItemViewLayout(int position) {
                // 单布局返回一种布局即可
                return android.R.layout.simple_list_item_1;
            }

            @Override
            public void onBindView(ViewHolder holder, List<String> data, int position) {
                holder.setText(android.R.id.text1, data.get(position));
            }
        });
    }


    private RecyclerView.Adapter getMultipleAdapter() {
        return new MultipleAdapter<>(data, new MultipleAdapter.OnBindViewListener<String>() {

            @Override
            public int getItemViewLayout(int position) {
                // 多布局时根据位置返回不同的布局文件
                return position % 2 == 0 ? android.R.layout.simple_list_item_1 : android.R.layout.simple_list_item_2;
            }

            @Override
            public void onBindView(ViewHolder holder, List<String> data, int position) {

                if (position % 2 == 0) {
                    holder.setText(android.R.id.text1, data.get(position));
                } else {
                    holder.setText(android.R.id.text1, data.get(position));
                    holder.setText(android.R.id.text2, "Android");
                }
            }
        });
    }
}

2. 单布局版-SimpleAdapter

public class SimpleAdapter<T> extends RecyclerView.Adapter<ViewHolder> {

    private final List<T> data;
    private final int layoutRes;
    private final OnBindViewListener<T> bindViewListener;

    public SimpleAdapter(@NonNull List<T> data, @LayoutRes int layoutRes, @NonNull OnBindViewListener<T> bindViewListener) {
        this.data = data;
        this.layoutRes = layoutRes;
        this.bindViewListener = bindViewListener;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
        return new ViewHolder(inflater.inflate(layoutRes, viewGroup, false));
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        if (bindViewListener != null) {
            bindViewListener.onBindView(holder, data, position);
        }
    }

    @Override
    public int getItemCount() {
        return data == null ? 0 : data.size();
    }

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


    /**
     * ItemView 设置接口(相对抽象函数灵活性、扩展性更好)
     * @param <T> 数据类型
     */
    public interface OnBindViewListener<T> {
        void onBindView(ViewHolder holder, List<T> data, int position);
    }
}

3. 多布局版-MultipleAdapter

  1. 让 getItemViewType() 函数返回布局文件, 而不是返回布局类型
  2. getItemViewType() 返回的布局文件会传递到给 onCreateViewHolder(), 这样我们就可以创建不同的布局文件 ViewHolder 了; 改几行代码就从单布局版变成了多布局版本了
public class MultipleAdapter<T> extends RecyclerView.Adapter<ViewHolder> {

    private final List<T> data;
    private final OnBindViewListener<T> bindViewListener;

    public MultipleAdapter(@NonNull List<T> data, @NonNull OnBindViewListener<T> bindViewListener) {
        this.data = data;
        this.bindViewListener = bindViewListener;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int layoutRes) {
        LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
        return new ViewHolder(inflater.inflate(layoutRes, viewGroup, false));
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        if (bindViewListener != null) {
            bindViewListener.onBindView(holder, data, position);
        }
    }

    @Override
    public int getItemCount() {
        return data == null ? 0 : data.size();
    }

    @Override
    public int getItemViewType(int position) {
        return bindViewListener == null ? View.NO_ID : bindViewListener.getItemViewLayout(position);
    }


    /**
     * ItemView 设置接口
     * @param <T> 数据类型
     */
    public interface OnBindViewListener<T> {

        int getItemViewLayout(int position);

        void onBindView(ViewHolder holder, List<T> data, int position);
    }
}

4. 通用 RecyclerHolder

/**
 * 通用 RecyclerView Holder
 */
public class ViewHolder extends RecyclerView.ViewHolder {

    private final Context context;
    private final SparseArray<View> mSparseArray;


    ViewHolder(@NonNull View itemView) {
        super(itemView);
        mSparseArray = new SparseArray<>();
        context = BaseApplication.getApplication();
    }

    @SuppressWarnings("unchecked")
    public final <T extends View> T getView(@IdRes int viewId) {
        View view = mSparseArray.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);     // 使用 RecyclerView.ViewHolder 保存的 itemView
            mSparseArray.put(viewId, view);
        }
        return (T) view;
    }


    /********************************** 常用函数 ****************************************/

    public ViewHolder setVisibility(int viewId, int visibility) {
        View view = getView(viewId);
        view.setVisibility(visibility);
        return this;
    }

    public ViewHolder setPadding(int viewId, int left, int top, int right, int bottom) {
        View view = getView(viewId);
        view.setPadding(left, top, right, bottom);
        return this;
    }

    public ViewHolder setSelected(int viewId, boolean selected) {
        View view = getView(viewId);
        view.setSelected(selected);
        return this;
    }

    public ViewHolder setBackgroundColor(int viewId, @ColorInt int color) {
        View view = getView(viewId);
        view.setBackgroundColor(color);
        return this;
    }

    public ViewHolder setBackgroundRes(int viewId, @DrawableRes int resId) {
        View view = getView(viewId);
        view.setBackgroundResource(resId);
        return this;
    }

    public ViewHolder setBackgroundDrawable(int viewId, Drawable drawable) {
        View view = getView(viewId);
        view.setBackground(drawable);
        return this;
    }

    public ViewHolder setBackgroundBitmap(int viewId, Bitmap bitmap) {
        View view = getView(viewId);
        view.setBackground(new BitmapDrawable(context.getResources(), bitmap));
        return this;
    }

    public ViewHolder setEnabled(int viewId, boolean enabled) {
        View view = getView(viewId);
        view.setEnabled(enabled);
        return this;
    }
    
    public boolean isEnabled(int viewId) {
        return getView(viewId).isEnabled();
    }



    /********************************** 常用监听 ****************************************/

    public ViewHolder setOnClickListener(int viewId, View.OnClickListener listener) {
        View view = getView(viewId);
        view.setOnClickListener(listener);
        return this;
    }

    public ViewHolder setOnTouchListener(int viewId, View.OnTouchListener listener) {
        View view = getView(viewId);
        view.setOnTouchListener(listener);
        return this;
    }

    public ViewHolder setOnLongClickListener(int viewId, View.OnLongClickListener listener) {
        View view = getView(viewId);
        view.setOnLongClickListener(listener);
        return this;
    }

    /**
     * 设置 RecyclerView item 点击监听
     * @param listener
     * @return
     */
    public ViewHolder setOnItemClickListener(View.OnClickListener listener) {
        itemView.setClickable(true);
        itemView.setOnClickListener(listener);
        return this;
    }

    /**
     * 设置 RecyclerView item 长按监听
     * @param listener
     * @return
     */
    public ViewHolder onItenLongClickListener(View.OnLongClickListener listener) {
        itemView.setLongClickable(true);
        itemView.setOnLongClickListener(listener);
        return this;
    }


    
    /********************************** TextView 相关函数 ****************************************/

    public ViewHolder setText(int viewId, CharSequence value) {
        TextView view = getView(viewId);
        view.setText(value);
        return this;
    }

    public ViewHolder setTextSize(int viewId, int testSize) {
        TextView view = getView(viewId);
        view.setTextSize(testSize);
        return this;
    }

    public ViewHolder setTextColor(int viewId, @ColorInt int textColor) {
        TextView view = getView(viewId);
        view.setTextColor(textColor);
        return this;
    }

    public ViewHolder setTextColorRes(int viewId, @ColorRes int color) {
        TextView view = getView(viewId);
        view.setTextColor(context.getResources().getColor(color));
        return this;
    }

    public ViewHolder setTextDrawable(int viewId, Drawable left, Drawable top, Drawable right, Drawable bottom) {
        TextView textView = getView(viewId);
        textView.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
        return this;
    }

    public ViewHolder addTextChangedListener(int viewId, TextWatcher watcher) {
        EditText editText = getView(viewId);
        editText.addTextChangedListener(watcher);
        return this;
    }



    /********************************** CheckBox 相关函数 ****************************************/

    public ViewHolder setOnCheckedChangeListener(int viewId, final CheckBox.OnCheckedChangeListener listener) {
        CheckBox checkBox = getView(viewId);
        checkBox.setOnCheckedChangeListener(listener);
        return this;
    }

    public ViewHolder setChecked(int viewId, boolean checked) {
        Checkable view = getView(viewId);
        view.setChecked(checked);
        return this;
    }

    public boolean isChecked(int viewId) {
        CheckBox checkBox = getView(viewId);
        return checkBox.isChecked();
    }



    /********************************** ProgressBar 相关函数 ****************************************/

    public ViewHolder setMax(int viewId, int max) {
        ProgressBar view = getView(viewId);
        view.setMax(max);
        return this;
    }

    public ViewHolder setPressed(int viewId, boolean pressed) {
        View view = getView(viewId);
        view.setPressed(pressed);
        return this;
    }



    /********************************** ImageView 相关函数 *****************************************/

    public ViewHolder setImageResource(int viewId, int imageResId) {
        ImageView view = getView(viewId);
        view.setImageResource(imageResId);
        return this;
    }

    public ViewHolder setImageDrawable(int viewId, Drawable drawable) {
        ImageView view = getView(viewId);
        view.setImageDrawable(drawable);
        return this;
    }

    public ViewHolder setImageBitmap(int viewId, Bitmap bitmap) {
        ImageView view = getView(viewId);
        view.setImageBitmap(bitmap);
        return this;
    }
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值