00-Unit_Common综述-RecyclerView封装
1 package top.toly.www.unit_common.bean;
2
3 /**
4 * 作者:张风捷特烈
5 * 时间:2018/4/10:14:55
6 * 邮箱:1981462002@qq.com
7 * 说明:每个界面的bean对象 图片+名称
8 */
9 public class ItemBean {
10
11 private String name;
12 private int ResId;
13
14 public ItemBean(String name, int resId) {
15 this.name = name;
16 ResId = resId;
17 }
18
19 public String getName() {
20 return name;
21 }
22
23 public void setName(String name) {
24 this.name = name;
25 }
26
27 public int getResId() {
28 return ResId;
29 }
30
31 public void setResId(int resId) {
32 ResId = resId;
33 }
34 }
1 注:笔者为避免寻找id的麻烦,使用了ButterKnife
2 依赖:implementation 'com.jakewharton:butterknife:7.0.1'
3 混淆:#butterknife
4 -keep class butterknife.** { *; }
5 -dontwarn butterknife.internal.**
6 -keep class **$$ViewBinder { *; }
7 -keepclasseswithmembernames class * {
8 @butterknife.* <fields>;
9 }
10 -keepclasseswithmembernames class * {
11 @butterknife.* <methods>;
12 }
1 package top.toly.www.unit_common.home;
2
3 import android.content.Intent;
4 import android.os.Bundle;
5 import android.support.v7.app.AppCompatActivity;
6 import android.support.v7.widget.RecyclerView;
7 import android.view.View;
8
9 import java.util.ArrayList;
10 import java.util.List;
11
12 import butterknife.Bind;
13 import butterknife.ButterKnife;
14 import top.toly.www.unit_common.R;
15 import top.toly.www.unit_common.activity.MainActivity;
16 import top.toly.www.unit_common.bean.ItemBean;
17 import utils.ev.recyclerview.MyRVAdapter;
18 import utils.ev.recyclerview.MyRVHolder;
19 import utils.ui.UIUtils;
20
21 public class Activity_Home_RV extends AppCompatActivity {
22
23 @Bind(R.id.recyclerview)
24 RecyclerView mRecyclerview;
25 private List<ItemBean> mItems;//itemBean的集合
26
27 @Override
28 protected void onCreate(Bundle savedInstanceState) {
29 super.onCreate(savedInstanceState);
30 setContentView(R.layout.activity_home_rv);
31 ButterKnife.bind(this);
32
33 setItemsData();//为item设置数据
34 initRV();//初始化RecyclerView
35
36 }
37
38 private void initRV() {
39 // 注:笔者已对RecyclerView进行封装,以下几行就搞定RecyclerView的简单使用,封装代码见下
40 UIUtils.setStyle4RV(mRecyclerview, 3, UIUtils.GRIDVIEW, this);//设置类型
41 MyRVAdapter<ItemBean> rvAdapter = new MyRVAdapter<ItemBean>(mItems, R.layout.rv_item_home) {
42 @Override
43 public void setDatas(MyRVHolder holder, ItemBean data, int position) {
44 holder.setText(R.id.tv_title, data.getName())
45 .setImageViewRes(R.id.iv_icon, data.getResId());
46 }
47 };
48
49 mRecyclerview.setAdapter(rvAdapter);
50 rvAdapter.setOnRvItemClickListener(new MyRVAdapter.OnRvItemClickListener() {
51 @Override
52 public void OnRvItemClick(View v, int pos) {
53 switch (pos) {
54 case 0:
55 startActivity(new Intent(Activity_Home_RV.this, MainActivity.class));
56 break;
57 }
58 }
59 });
60 }
61
62 /**
63 * 为item设置数据
64 *
65 * @return
66 */
67
68 public List<ItemBean> setItemsData() {
69 mItems = new ArrayList<>();
70 mItems.add(new ItemBean("test", R.drawable.ic_launcher_background));
71 mItems.add(new ItemBean("test1", R.drawable.ic_launcher_background));
72 return mItems;
73 }
74
75 }
1 <?xml version="1.0" encoding="utf-8"?>
2 <RelativeLayout
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:tools="http://schemas.android.com/tools"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent">
7
8 <android.support.v7.widget.RecyclerView
9 android:id="@+id/recyclerview"
10 android:layout_width="match_parent"
11 android:layout_height="wrap_content"/>
12
13 </RelativeLayout>
1 <?xml version="1.0" encoding="utf-8"?>
2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="match_parent"
4 android:layout_height="wrap_content"
5 android:padding="5dp">
6
7 <ImageView
8 android:id="@+id/iv_icon"
9 android:layout_width="50dp"
10 android:layout_height="50dp"
11 android:src="@drawable/ic_launcher_background" />
12
13 <TextView
14 android:id="@+id/tv_title"
15 android:layout_width="match_parent"
16 android:layout_height="wrap_content"
17 android:layout_marginLeft="3dp"
18 android:layout_toRightOf="@+id/iv_icon"
19 android:layout_centerInParent="true"
20 android:text="Content"
21 android:textAllCaps="false"
22 android:textColor="#000000" />
23 </RelativeLayout>
1 package utils.ev.recyclerview; 2 3 import android.graphics.Bitmap; 4 import android.support.v7.widget.RecyclerView; 5 import android.util.SparseArray; 6 import android.view.View; 7 import android.widget.ImageView; 8 import android.widget.TextView; 9 10 import com.bumptech.glide.Glide; 11 import com.bumptech.glide.load.engine.DiskCacheStrategy; 12 13 import utils.ui.UIUtils; 14 15 /** 16 * 作者:张风捷特烈 17 * 时间:2018/4/10:14:22 18 * 邮箱:1981462002@qq.com 19 * 说明:View的持有人 20 */ 21 public class MyRVHolder extends RecyclerView.ViewHolder { 22 23 //键值对中键是int类型使用SparseArray比map更好 24 private SparseArray<View> mViews;//持有的所有View集合 25 private View mItemView;//Item的 26 27 public MyRVHolder(View itemView) { 28 29 super(itemView); 30 mItemView = itemView; 31 mViews = new SparseArray<>(); 32 } 33 34 /** 35 * 获取pos 36 * 37 * @return 38 */ 39 public int getPos() { 40 return this.getLayoutPosition(); 41 } 42 43 /** 44 * 通过viewId获取控件 45 * 46 * @param viewId 47 * @param <T> 48 * @return 49 */ 50 public <T extends View> T getView(int viewId) { 51 View view = mViews.get(viewId); 52 if (view == null) { 53 view = mItemView.findViewById(viewId); 54 mViews.put(viewId, view);//以id为键,view为值 55 } 56 return (T) view; 57 } 58 59 public View getItemView() { 60 return mItemView; 61 } 62 63 /** 64 * 设置item背景颜色 65 */ 66 public MyRVHolder setColor(int color) { 67 mItemView.setBackgroundColor(color); 68 return this; 69 } 70 71 /** 72 * 设置TextView文本方法 73 * 74 * @param viewId 75 * @param text 76 * @return 77 */ 78 public MyRVHolder setText(int viewId, String text) { 79 TextView view = getView(viewId); 80 view.setText(text); 81 return this; 82 } 83 84 /** 85 * 通过资源id设置ImageView图片 86 * @param viewId 87 * @param resId 88 * @return 89 */ 90 public MyRVHolder setImageViewRes(int viewId, int resId) { 91 ImageView view = getView(viewId); 92 view.setImageResource(resId); 93 return this; 94 } 95 96 /** 97 * 通过Bitmap设置ImageView图片 98 * @param viewId 99 * @param bitmap 100 * @return 101 */ 102 public MyRVHolder setImageViewBitmap(int viewId, Bitmap bitmap) { 103 ImageView view = getView(viewId); 104 view.setImageBitmap(bitmap); 105 return this; 106 } 107 108 /** 109 * 通过url设置图片 110 * @param viewId 111 * @param url 112 * @return 113 */ 114 public MyRVHolder setImageViewUrl(int viewId, String url) { 115 ImageView view = getView(viewId); 116 //此处使用Glide进行Url类型图片的加载,如果未添加Glide依赖会报错 117 //依赖: implementation 'com.github.bumptech.glide:glide:3.7.0' 118 Glide.with(UIUtils.getContext()) 119 .load(url) 120 .skipMemoryCache(false) 121 .diskCacheStrategy(DiskCacheStrategy.SOURCE) 122 .into(view); 123 124 return this; 125 } 126 127 /////////////////////可继续拓展完善,添加更多方法////////////////////// 128 }
1 package utils.ev.recyclerview; 2 3 import android.support.v7.widget.RecyclerView; 4 import android.view.View; 5 import android.view.ViewGroup; 6 7 import java.util.List; 8 9 import utils.ui.UIUtils; 10 11 /** 12 * 作者:张风捷特烈 13 * 时间:2018/4/10:14:28 14 * 邮箱:1981462002@qq.com 15 * 说明:RecyclerView的Adapter封装类 16 */ 17 public abstract class MyRVAdapter<T> extends RecyclerView.Adapter<MyRVHolder> { 18 protected List<T> mDatas; 19 protected int mItemId; 20 private View mItemView; 21 22 public MyRVAdapter(List<T> datas, int itemId) { 23 mDatas = datas; 24 mItemId = itemId; 25 } 26 27 @Override 28 public MyRVHolder onCreateViewHolder(ViewGroup parent, int viewType) { 29 mItemView = UIUtils.inflate(mItemId); 30 final MyRVHolder myRVHolder = new MyRVHolder(mItemView); 31 //点击事件方式 32 mItemView.setOnClickListener(new View.OnClickListener() { 33 @Override 34 public void onClick(View v) {//使用回调实现点击监听 35 if (mOnRvItemClickListener != null) { 36 mOnRvItemClickListener.OnRvItemClick(v, myRVHolder.getPos()); 37 38 } 39 } 40 }); 41 42 return myRVHolder; 43 } 44 45 @Override 46 public void onBindViewHolder(MyRVHolder holder, int position) { 47 48 setDatas(holder, mDatas.get(position), position); 49 50 } 51 52 @Override 53 public int getItemCount() { 54 return mDatas.size(); 55 } 56 57 /** 58 * 抽象方法,通过holder可对各控件进行操作 59 * 60 * @param holder View的持有人 61 * @param data 数据 62 * @param position 点击位置 63 */ 64 public abstract void setDatas(MyRVHolder holder, T data, int position); 65 66 /////////////////////////////////////////////////////////// 67 68 /** 69 * 添加item 70 * 71 * @param i 72 * @param aNew 73 */ 74 public void addData(int i, T aNew) { 75 mDatas.add(i, aNew); 76 notifyItemInserted(i);//刷新数据 77 } 78 79 /** 80 * 删除item 81 * 82 * @param i 83 */ 84 public void deleteData(int i) { 85 mDatas.remove(i); 86 notifyItemRemoved(i);//刷新数据 87 } 88 89 public View getItemView() { 90 return mItemView; 91 } 92 93 /////////////////为RecyclerView设置点击监听接口///////////////////////// 94 /** 95 * 为RecyclerView设置点击监听接口 96 */ 97 public interface OnRvItemClickListener { 98 void OnRvItemClick(View v, int pos);//item被点击的时候回调方法 99 } 100 101 /** 102 * 声明监听器接口对象 103 */ 104 private OnRvItemClickListener mOnRvItemClickListener; 105 106 /** 107 * 设置RecyclerView某个的监听方法 108 * 109 * @param onRvItemClickListener 110 */ 111 public void setOnRvItemClickListener(OnRvItemClickListener onRvItemClickListener) { 112 mOnRvItemClickListener = onRvItemClickListener; 113 } 114 }
这样可以使用了,不过为了添加分割线,还有免去写一些初始化的设置方法,把其封装在我的UiUtils中,静态方法如下:
1 ////////////////////////设置RecyclerView///////////////////////////////////////// 2 public static final int GRIDVIEW = 0; 3 public static final int LISTVIEW = 1; 4 public static final int PULL = 2; 5 6 /** 7 * 8 * @param rv RecyclerView 9 * @param count count 数量 LISTVIEW可随意 10 * @param style 模式 GRIDVIEW LISTVIEW PULL 11 * @param ctx 上下文 12 */ 13 public static GridLayoutManager setStyle4RV(RecyclerView rv, int count, int style,Context ctx) { 14 switch (style) { 15 case GRIDVIEW://GridView类型 16 rv.addItemDecoration(new MyDividerItemDecoration(ctx));//设置分割线 17 GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), count, GridLayoutManager.VERTICAL, false); 18 rv.setLayoutManager(gridLayoutManager); 19 return gridLayoutManager; 20 case LISTVIEW://ListView类型 21 rv.addItemDecoration(new SampleDivider(ctx)); 22 rv.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false)); 23 return null; 24 case PULL://瀑布流类型 25 rv.addItemDecoration(new MyDividerItemDecoration(ctx)); 26 rv.setLayoutManager(new StaggeredGridLayoutManager(count, StaggeredGridLayoutManager.VERTICAL)); 27 return null; 28 } 29 return null; 30 }
1 package utils.ev.recyclerview; 2 3 import android.content.Context; 4 import android.content.res.TypedArray; 5 import android.graphics.Canvas; 6 import android.graphics.Rect; 7 import android.graphics.drawable.Drawable; 8 import android.support.v7.widget.GridLayoutManager; 9 import android.support.v7.widget.OrientationHelper; 10 import android.support.v7.widget.RecyclerView; 11 import android.view.View; 12 13 14 public class MyDividerItemDecoration extends RecyclerView.ItemDecoration { 15 16 private static final int[] ATTRS = new int[]{ 17 android.R.attr.listDivider 18 }; 19 20 /** 21 * 用于绘制间隔样式 22 */ 23 private Drawable mDivider; 24 25 public MyDividerItemDecoration(Context context) { 26 // 获取默认主题的属性 27 final TypedArray a = context.obtainStyledAttributes(ATTRS); 28 mDivider = a.getDrawable(0); 29 a.recycle(); 30 } 31 32 33 @Override 34 public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { 35 // 绘制间隔,每一个item,绘制右边和下方间隔样式 36 int childCount = parent.getChildCount(); 37 int spanCount = ((GridLayoutManager)parent.getLayoutManager()).getSpanCount(); 38 int orientation = ((GridLayoutManager)parent.getLayoutManager()).getOrientation(); 39 boolean isDrawHorizontalDivider = true; 40 boolean isDrawVerticalDivider = true; 41 int extra = childCount % spanCount; 42 extra = extra == 0 ? spanCount : extra; 43 for(int i = 0; i < childCount; i++) { 44 isDrawVerticalDivider = true; 45 isDrawHorizontalDivider = true; 46 // 如果是竖直方向,最右边一列不绘制竖直方向的间隔 47 if(orientation == OrientationHelper.VERTICAL && (i + 1) % spanCount == 0) { 48 isDrawVerticalDivider = false; 49 } 50 51 // 如果是竖直方向,最后一行不绘制水平方向间隔 52 if(orientation == OrientationHelper.VERTICAL && i >= childCount - extra) { 53 isDrawHorizontalDivider = false; 54 } 55 56 // 如果是水平方向,最下面一行不绘制水平方向的间隔 57 if(orientation == OrientationHelper.HORIZONTAL && (i + 1) % spanCount == 0) { 58 isDrawHorizontalDivider = false; 59 } 60 61 // 如果是水平方向,最后一列不绘制竖直方向间隔 62 if(orientation == OrientationHelper.HORIZONTAL && i >= childCount - extra) { 63 isDrawVerticalDivider = false; 64 } 65 66 if(isDrawHorizontalDivider) { 67 drawHorizontalDivider(c, parent, i); 68 } 69 70 if(isDrawVerticalDivider) { 71 drawVerticalDivider(c, parent, i); 72 } 73 } 74 } 75 76 @Override 77 public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 78 int spanCount = ((GridLayoutManager) parent.getLayoutManager()).getSpanCount(); 79 int orientation = ((GridLayoutManager)parent.getLayoutManager()).getOrientation(); 80 int position = parent.getChildLayoutPosition(view); 81 if(orientation == OrientationHelper.VERTICAL && (position + 1) % spanCount == 0) { 82 outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); 83 return; 84 } 85 86 if(orientation == OrientationHelper.HORIZONTAL && (position + 1) % spanCount == 0) { 87 outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); 88 return; 89 } 90 91 outRect.set(0, 0, mDivider.getIntrinsicWidth(), mDivider.getIntrinsicHeight()); 92 } 93 94 /** 95 * 绘制竖直间隔线 96 * 97 * @param canvas 98 * @param parent 99 * 父布局,RecyclerView 100 * @param position 101 * irem在父布局中所在的位置 102 */ 103 private void drawVerticalDivider(Canvas canvas, RecyclerView parent, int position) { 104 final View child = parent.getChildAt(position); 105 final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child 106 .getLayoutParams(); 107 final int top = child.getTop() - params.topMargin; 108 final int bottom = child.getBottom() + params.bottomMargin + mDivider.getIntrinsicHeight(); 109 final int left = child.getRight() + params.rightMargin; 110 final int right = left + mDivider.getIntrinsicWidth(); 111 mDivider.setBounds(left, top, right, bottom); 112 mDivider.draw(canvas); 113 } 114 115 /** 116 * 绘制水平间隔线 117 * 118 * @param canvas 119 * @param parent 120 * 父布局,RecyclerView 121 * @param position 122 * item在父布局中所在的位置 123 */ 124 private void drawHorizontalDivider(Canvas canvas, RecyclerView parent, int position) { 125 final View child = parent.getChildAt(position); 126 final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child 127 .getLayoutParams(); 128 final int top = child.getBottom() + params.bottomMargin; 129 final int bottom = top + mDivider.getIntrinsicHeight(); 130 final int left = child.getLeft() - params.leftMargin; 131 final int right = child.getRight() + params.rightMargin + mDivider.getIntrinsicWidth(); 132 mDivider.setBounds(left, top, right, bottom); 133 mDivider.draw(canvas); 134 } 135 }