Linjiajia
2023-04-24 fcdddf8b9b34f9930bec454b5fffe41c0e33ba3c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
package com.android.app_base.base.adapter;
 
import android.content.Context;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
 
import androidx.annotation.IdRes;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
 
import java.util.ArrayList;
import java.util.List;
 
/**
 * @author Ljj
 * @date 2023.03.02. 17:09
 * @desc RecyclerView 适配器基类
 */
public abstract class BaseRVAdapter<T,VDB extends ViewDataBinding,VH extends BaseRVAdapter.BaseViewHolder<VDB>> extends RecyclerView.Adapter<VH> {
 
    /** 上下文对象 */
    protected final Context mContext;
 
    /** RecyclerView 对象 */
    protected RecyclerView mRecyclerView;
 
    /** 条目点击监听器 */
    protected OnItemClickListener mItemClickListener;
    /** 条目长按监听器 */
    protected OnItemLongClickListener mItemLongClickListener;
    /**
     * 该 adapter 上绑定的滑动监听器
     */
    protected MyOnScrollListener myOnScrollListener;
 
    /** 条目子 View 点击监听器 */
    protected SparseArray<OnChildClickListener> mChildClickListeners;
    /** 条目子 View 长按监听器 */
    protected SparseArray<OnChildLongClickListener> mChildLongClickListeners;
    /**
     * 列表数据
     */
    protected List<T> mDataList;
 
    public BaseRVAdapter(Context context) {
        mContext = context;
        if (mContext == null) {
            throw new IllegalArgumentException("are you ok?");
        }
    }
 
    public BaseRVAdapter(Context context, List<T> list) {
        mContext = context;
        mDataList = (list == null) ? new ArrayList<T>() : list;
        setData(list);
    }
 
 
    @NonNull
    @Override
    public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        VDB itemBind = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),getLayoutId(),parent,false);
        return getViewHolder(itemBind,viewType);
    }
 
    protected abstract int getLayoutId();
    protected abstract void onBind(VH holder, int position);
    protected abstract VH getViewHolder(VDB itemBind,int viewType);
 
    @Override
    public void onBindViewHolder(@NonNull VH holder, int position) {
        View itemView = holder.itemView;
        // 设置条目的点击和长按事件
        if (mItemClickListener != null) {
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    mItemClickListener.onItemClick(mRecyclerView,view, holder.getLayoutPosition());
                }
            });
        }
        if (mItemLongClickListener != null) {
            itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    return mItemLongClickListener.onItemLongClick(mRecyclerView, view, holder.getLayoutPosition());
                }
            });
        }
 
        // 设置条目子 View 点击事件
        if (mChildClickListeners != null) {
            for (int i = 0; i < mChildClickListeners.size(); i++) {
                View childView = itemView.findViewById(mChildClickListeners.keyAt(i));
                if (childView != null) {
                    childView.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            OnChildClickListener listener = mChildClickListeners.get(view.getId());
                            if (listener != null) {
                                listener.onChildClick(mRecyclerView, view, holder.getLayoutPosition());
                            }
                        }
                    });
                }
            }
        }
 
        // 设置条目子 View 长按事件
        if (mChildLongClickListeners != null) {
            for (int i = 0; i < mChildLongClickListeners.size(); i++) {
                View childView = itemView.findViewById(mChildLongClickListeners.keyAt(i));
                if (childView != null) {
                    childView.setOnLongClickListener(new View.OnLongClickListener() {
                        @Override
                        public boolean onLongClick(View view) {
                            OnChildLongClickListener listener = mChildLongClickListeners.get(view.getId());
                            if (listener != null) {
                                return listener.onChildLongClick(mRecyclerView, view, holder.getLayoutPosition());
                            }
                            return false;
                        }
                    });
                }
            }
        }
        onBind(holder,position);
    }
 
 
    @Override
    public int getItemCount() {
        return mDataList == null ? 0 : mDataList.size();
    }
 
    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        mRecyclerView = recyclerView;
        // 用户设置了滚动监听,需要给 RecyclerView 设置监听
        if (myOnScrollListener != null) {
            // 添加滚动监听
            mRecyclerView.addOnScrollListener(myOnScrollListener);
        }
        // 判断当前的布局管理器是否为空,如果为空则设置默认的布局管理器
        if (mRecyclerView.getLayoutManager() == null) {
            RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(mContext);;
            mRecyclerView.setLayoutManager(layoutManager);
        }
    }
 
    @Override
    public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
        // 移除滚动监听
        if (myOnScrollListener != null) {
            mRecyclerView.removeOnScrollListener(myOnScrollListener);
        }
        mRecyclerView = null;
    }
 
    public RecyclerView getRecyclerView() {
        return mRecyclerView;
    }
 
    /**
     * 自定义ViewHolder,基类
     * @param <VDB>
     */
    public static class BaseViewHolder<VDB extends ViewDataBinding> extends RecyclerView.ViewHolder{
        protected VDB binding;
        public BaseViewHolder(@NonNull View itemView) {
            super(itemView);
 
        }
        public BaseViewHolder(VDB binding) {
            this(binding.getRoot());
            this.binding = binding;
        }
 
        public VDB getBinding() {
            return binding;
        }
    }
    /**
     * 设置新的数据
     */
    public void setData(@Nullable List<T> data) {
        mDataList = data;
        notifyDataSetChanged();
    }
    /**
     * 获取当前数据
     */
    @Nullable
    public List<T> getData() {
        return mDataList;
    }
    /**
     * 追加一些数据
     */
    public void addData(List<T> data) {
        if (data == null || data.size() == 0) {
            return;
        }
 
        if (mDataList == null || mDataList.size() == 0) {
            setData(data);
        } else {
            //一个一个的添加
            for (T datum : data) {
                addItem(datum);
            }
        }
    }
    /**
     * 从头部 追加一些数据
     */
    public void addDataFromHead(List<T> data) {
        if (data == null || data.size() == 0) {
            return;
        }
 
        if (mDataList == null || mDataList.size() == 0) {
            setData(data);
        } else {
            mDataList.addAll(0, data);
            notifyDataSetChanged();
        }
    }
    /**
     * 清空当前数据
     */
    public void clearData() {
        if (mDataList == null || mDataList.size() == 0) {
            return;
        }
        mDataList.clear();
        notifyDataSetChanged();
    }
    /**
     * 获取某个位置上的数据
     */
    public T getItem(@IntRange(from = 0) int position) {
        return mDataList.get(position);
    }
 
    /**
     * 更新某个位置上的数据
     */
    public void setItem(@IntRange(from = 0) int position, @NonNull T item) {
        if (mDataList == null) {
            mDataList = new ArrayList<>();
        }
        mDataList.set(position, item);
        notifyItemChanged(position);
    }
    /**
     * 添加单条数据
     */
    public void addItem(@NonNull T item) {
        if (mDataList == null) {
            mDataList = new ArrayList<>();
        }
 
        addItem(mDataList.size(), item);
    }
 
    public void addItem(@IntRange(from = 0) int position, @NonNull T item) {
        if (mDataList == null) {
            mDataList = new ArrayList<>();
        }
 
        if (position < mDataList.size()) {
            mDataList.add(position, item);
        } else {
            mDataList.add(item);
            position = mDataList.size() - 1;
        }
        notifyItemInserted(position);
    }
    /**
     * 删除单条数据
     */
    public void removeItem(@NonNull T item) {
        int index = mDataList.indexOf(item);
        if (index != -1) {
            removeItem(index);
        }
    }
    public void removeItem(@IntRange(from = 0) int position) {
        // 如果是在for循环删除后要记得i--
        mDataList.remove(position);
        // 告诉适配器删除数据的位置,会有动画效果
        notifyItemRemoved(position);
    }
    /**
     * 设置 RecyclerView 条目点击监听
     */
    public void setOnItemClickListener(OnItemClickListener listener) {
        checkRecyclerViewState();
        mItemClickListener = listener;
    }
 
    /**
     * 设置 RecyclerView 条目子 View 点击监听
     */
    public void setOnChildClickListener(@IdRes int id, OnChildClickListener listener) {
        checkRecyclerViewState();
        if (mChildClickListeners == null) {
            mChildClickListeners = new SparseArray<>();
        }
        mChildClickListeners.put(id, listener);
    }
 
    /**
     * 设置RecyclerView条目长按监听
     */
    public void setOnItemLongClickListener(OnItemLongClickListener listener) {
        checkRecyclerViewState();
        mItemLongClickListener = listener;
    }
 
    /**
     * 设置 RecyclerView 条目子 View 长按监听
     */
    public void setOnChildLongClickListener(@IdRes int id, OnChildLongClickListener listener) {
        checkRecyclerViewState();
        if (mChildLongClickListeners == null) {
            mChildLongClickListeners = new SparseArray<>();
        }
        mChildLongClickListeners.put(id, listener);
    }
 
    private void checkRecyclerViewState() {
        if (mRecyclerView != null) {
            // 必须在 RecyclerView.setAdapter() 之前设置监听
            throw new IllegalStateException("are you ok?");
        }
    }
    /**
     * 设置 RecyclerView 条目滚动监听
     */
    public void setOnScrollingListener(OnScrollingListener listener) {
        /** RecyclerView 滚动事件监听 */
        //如果当前已经有设置滚动监听,再次设置需要移除原有的监听器
        if (myOnScrollListener == null) {
            myOnScrollListener = new MyOnScrollListener(listener);
        } else {
            mRecyclerView.removeOnScrollListener(myOnScrollListener);
        }
        //用户设置了滚动监听,需要给RecyclerView设置监听
        //用户设置了滚动监听,需要给RecyclerView设置监听
        if (mRecyclerView != null) {
            //添加滚动监听
            mRecyclerView.addOnScrollListener(new MyOnScrollListener(listener));
        }
    }
 
 
    /**
     * RecyclerView 条目点击监听类
     */
    public interface OnItemClickListener{
 
        /**
         * 当 RecyclerView 某个条目被点击时回调
         *
         * @param recyclerView      RecyclerView 对象
         * @param itemView          被点击的条目对象
         * @param position          被点击的条目位置
         */
        void onItemClick(RecyclerView recyclerView, View itemView, int position);
    }
 
    /**
     * RecyclerView 条目长按监听类
     */
    public interface OnItemLongClickListener {
 
        /**
         * 当 RecyclerView 某个条目被长按时回调
         *
         * @param recyclerView      RecyclerView 对象
         * @param itemView          被点击的条目对象
         * @param position          被点击的条目位置
         * @return                  是否拦截事件
         */
        boolean onItemLongClick(RecyclerView recyclerView, View itemView, int position);
    }
 
    /**
     * RecyclerView 条目子 View 点击监听类
     */
    public interface OnChildClickListener {
 
        /**
         * 当 RecyclerView 某个条目 子 View 被点击时回调
         *
         * @param recyclerView      RecyclerView 对象
         * @param childView         被点击的条目子 View
         * @param position          被点击的条目位置
         */
        void onChildClick(RecyclerView recyclerView, View childView, int position);
    }
 
    /**
     * RecyclerView 条目子 View 长按监听类
     */
    public interface OnChildLongClickListener {
 
        /**
         * 当 RecyclerView 某个条目子 View 被长按时回调
         *
         * @param recyclerView      RecyclerView 对象
         * @param childView         被点击的条目子 View
         * @param position          被点击的条目位置
         */
        boolean onChildLongClick(RecyclerView recyclerView, View childView, int position);
    }
    /**
     * RecyclerView 滚动监听接口
     */
    public interface OnScrollingListener {
 
        /**
         * 列表滚动到最顶部
         *
         * @param recyclerView      RecyclerView 对象
         */
        void onScrollTop(RecyclerView recyclerView);
 
        /**
         * 列表滚动中
         *
         * @param recyclerView      RecyclerView 对象
         */
        void onScrolling(RecyclerView recyclerView);
 
        /**
         * 列表滚动到最底部
         *
         * @param recyclerView      RecyclerView 对象
         */
        void onScrollDown(RecyclerView recyclerView);
    }
 
    /**
     * 自定义RecyclerView的滑动监听器
     */
    public static class MyOnScrollListener extends RecyclerView.OnScrollListener {
        private OnScrollingListener onScrollingListener;
        MyOnScrollListener(OnScrollingListener onScrollingListener){
            this.onScrollingListener = onScrollingListener;
        }
        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            if (onScrollingListener == null) {
                return;
            }
 
            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
 
                if (!recyclerView.canScrollVertically(1)) {
                    // 已经到底了
                    onScrollingListener.onScrollDown(recyclerView);
                } else if (!recyclerView.canScrollVertically(-1)) {
                    // 已经到顶了
                    onScrollingListener.onScrollTop(recyclerView);
                }
 
            } else if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
                // 正在滚动中
                onScrollingListener.onScrolling(recyclerView);
            }
        }
    }
}