Android RecyclerView網(wǎng)格布局(支持多種分割線)詳解(2)
上篇Android RecyclerView 詳解(1)—線性布局
記錄了下RecyclerView的使用方法,并且講述了線性布局列表的使用方法,在此基礎(chǔ)上加上了萬(wàn)能分割線,支持顏色分割線和圖片分割線,同時(shí)支持對(duì)分割線設(shè)置線寬。
這篇是總結(jié)一下網(wǎng)格布局的使用,同樣也支持兩種分割線和線寬的設(shè)置。
主要的相關(guān)類:
1. RecyclerView.Adapter
2. GridLayoutManager 網(wǎng)格布局管理器
3. RecycleView.ItemDecoration 分割線
下面就直接通過(guò)一個(gè)例子來(lái)展示:
先上效果圖:
(1) 顏色分割線
看起來(lái)還不錯(cuò)吧,根據(jù)item的數(shù)量去顯示格子,當(dāng)然如果你需要的樣式不是三列,這個(gè)很簡(jiǎn)單,只需要在設(shè)置
GridLayoutManager的時(shí)候設(shè)置相應(yīng)的列數(shù)即可,即:
mManagerLayout = new GridLayoutManager(getActivity(), 3);
(2) 圖片分割線
可能有人會(huì)說(shuō)你的列表四周都有分割線,其實(shí)在不做特殊處理時(shí)左邊和上面默認(rèn)是沒(méi)有分割線的。后面我會(huì)加上四周沒(méi)有分割線的,其實(shí)這兩種形式在實(shí)際開(kāi)發(fā)中都是常見(jiàn)的,先來(lái)看四周都有邊線的。
由于RecycleView是高度解耦的控件,繪制分割線只和 RecycleView.ItemDecoration 有關(guān),所以我們只需關(guān)心怎么去繼承 RecycleView.ItemDecoration 去實(shí)現(xiàn)我們所需的分割線,如下:
這里需要說(shuō)明的是:顏色分割線和圖片分割線原理是完全一樣的,圖片分割線只是將一張很細(xì)的圖片傳入即可。
public class GridDivider extends RecyclerView.ItemDecoration { private Drawable mDividerDarwable; private int mDividerHight = 1; private Paint mColorPaint; public final int[] ATRRS = new int[]{android.R.attr.listDivider}; public GridDivider(Context context) { final TypedArray ta = context.obtainStyledAttributes(ATRRS); this.mDividerDarwable = ta.getDrawable(0); ta.recycle(); } /* int dividerHight 分割線的線寬 int dividerColor 分割線的顏色 */ public GridDivider(Context context, int dividerHight, int dividerColor) { this(context); mDividerHight = dividerHight; //繪制顏色分割線的畫筆 mColorPaint = new Paint(); mColorPaint.setColor(dividerColor); } /* int dividerHight 分割線的線寬 Drawable dividerDrawable 圖片分割線 */ public GridDivider(Context context, int dividerHight, Drawable dividerDrawable) { this(context); mDividerHight = dividerHight; mDividerDarwable = dividerDrawable; } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); //畫水平和垂直分割線 drawHorizontalDivider(c, parent); drawVerticalDivider(c, parent); } public void drawVerticalDivider(Canvas c, RecyclerView parent) { // 這里傳入的parent是recycleview,通過(guò)它我們可以獲取列表的所有的元素, // 這里我們遍歷列表中的每一個(gè)元素,對(duì)每一個(gè)元素繪制垂直分割線 final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); //獲取當(dāng)前item布局參數(shù),通過(guò)它可以知道該item的精確位置,我們通過(guò)這個(gè)位置去繪制它的分割線 final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int top = child.getTop() - params.topMargin; final int bottom = child.getBottom() + params.bottomMargin; int left = 0; int right = 0; //左邊第一列, if ((i % 3) == 0) { //item左邊分割線 left = child.getLeft(); right = left + mDividerHight; mDividerDarwable.setBounds(left, top, right, bottom); mDividerDarwable.draw(c); if (mColorPaint != null) {//如果是顏色分割線 c.drawRect(left, top, right, bottom, mColorPaint); } //item右邊分割線 left = child.getRight() + params.rightMargin - mDividerHight; right = left + mDividerHight; } else { //非左邊第一列 left = child.getRight() + params.rightMargin - mDividerHight; right = left + mDividerHight; } //畫分割線 mDividerDarwable.setBounds(left, top, right, bottom); mDividerDarwable.draw(c); if (mColorPaint != null) { c.drawRect(left, top, right, bottom, mColorPaint); } } } //....水平分割線與垂直分割線類似,完整代碼見(jiàn)下。 }
下面是完整代碼:
1. MainActivity
public class MainActivity extends AppCompatActivity { private GridFragment mGridFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //網(wǎng)格 mGridFragment = new GridFragment(); getFragmentManager().beginTransaction().replace(R.id.activity_main, mGridFragment).commit(); }
activity_main
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent"> </FrameLayout>
2. GridFragment
public class GridFragment extends Fragment implements View.OnClickListener{ private RecyclerView mRecycleViewDrawable; private RecyclerView mRecycleViewColor; private LinearLayoutManager mManagerColor; private LinearLayoutManager mManagerDrawable; private List<String> mData; private Button mDrawable; private Button mColor; private MyRecycleViewAdapter mRecycleViewAdapter; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_grid_layout, container, false); mRecycleViewDrawable = (RecyclerView) view.findViewById(R.id.recycleview_drawable); mRecycleViewColor = (RecyclerView) view.findViewById(R.id.recycleview_color); mDrawable = (Button) view.findViewById(R.id.btn_drawable); mDrawable.setOnClickListener(this); mColor = (Button) view.findViewById(R.id.btn_color); mColor.setOnClickListener(this); //設(shè)置顏色分割線 mManagerColor = new GridLayoutManager(getActivity(), 3); mRecycleViewColor.setLayoutManager(mManagerColor); mRecycleViewColor.addItemDecoration(new GridDivider(getActivity(), 20, this.getResources().getColor(R.color.colorAccent))); //設(shè)置圖片分割線 mManagerDrawable = new GridLayoutManager(getActivity(), 3); mRecycleViewDrawable.setLayoutManager(mManagerDrawable); Drawable drawable = ContextCompat.getDrawable(getActivity(), R.mipmap.divider); mRecycleViewDrawable.addItemDecoration(new GridDivider(getActivity(), 20, drawable)); //初始化數(shù)據(jù) mData = new ArrayList<String>(); initData(mData); mRecycleViewAdapter = new MyRecycleViewAdapter(getActivity(), R.layout.item_grid_recycleview, mData); mRecycleViewColor.setAdapter(mRecycleViewAdapter); mRecycleViewDrawable.setAdapter(mRecycleViewAdapter); return view; } private void initData(List<String> dataList) { for (int i = 0; i < 16; i++) { dataList.add("item" + i); } } @Override public void onClick(View view) { int id = view.getId(); switch (id){ case R.id.btn_drawable: mRecycleViewColor.setVisibility(View.INVISIBLE); mRecycleViewDrawable.setVisibility(View.VISIBLE); break; case R.id.btn_color: mRecycleViewColor.setVisibility(View.VISIBLE); mRecycleViewDrawable.setVisibility(View.INVISIBLE); break; } } }
3.分割線 GridDivider
直接繼承 RecyclerView.ItemDecoration
public class GridDivider extends RecyclerView.ItemDecoration { private Drawable mDividerDarwable; private int mDividerHight = 1; private Paint mColorPaint; public final int[] ATRRS = new int[]{android.R.attr.listDivider}; public GridDivider(Context context) { final TypedArray ta = context.obtainStyledAttributes(ATRRS); this.mDividerDarwable = ta.getDrawable(0); ta.recycle(); } /* int dividerHight 分割線的線寬 int dividerColor 分割線的顏色 */ public GridDivider(Context context, int dividerHight, int dividerColor) { this(context); mDividerHight = dividerHight; mColorPaint = new Paint(); mColorPaint.setColor(dividerColor); } /* int dividerHight 分割線的線寬 Drawable dividerDrawable 圖片分割線 */ public GridDivider(Context context, int dividerHight, Drawable dividerDrawable) { this(context); mDividerHight = dividerHight; mDividerDarwable = dividerDrawable; } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); //畫水平和垂直分割線 drawHorizontalDivider(c, parent); drawVerticalDivider(c, parent); } public void drawVerticalDivider(Canvas c, RecyclerView parent) { final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int top = child.getTop() - params.topMargin; final int bottom = child.getBottom() + params.bottomMargin; int left = 0; int right = 0; //左邊第一列 if ((i % 3) == 0) { //item左邊分割線 left = child.getLeft(); right = left + mDividerHight; mDividerDarwable.setBounds(left, top, right, bottom); mDividerDarwable.draw(c); if (mColorPaint != null) { c.drawRect(left, top, right, bottom, mColorPaint); } //item右邊分割線 left = child.getRight() + params.rightMargin - mDividerHight; right = left + mDividerHight; } else { //非左邊第一列 left = child.getRight() + params.rightMargin - mDividerHight; right = left + mDividerHight; } //畫分割線 mDividerDarwable.setBounds(left, top, right, bottom); mDividerDarwable.draw(c); if (mColorPaint != null) { c.drawRect(left, top, right, bottom, mColorPaint); } } } public void drawHorizontalDivider(Canvas c, RecyclerView parent) { final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int left = child.getLeft() - params.leftMargin - mDividerHight; final int right = child.getRight() + params.rightMargin; int top = 0; int bottom = 0; // 最上面一行 if ((i / 3) == 0) { //當(dāng)前item最上面的分割線 top = child.getTop(); //當(dāng)前item下面的分割線 bottom = top + mDividerHight; mDividerDarwable.setBounds(left, top, right, bottom); mDividerDarwable.draw(c); if (mColorPaint != null) { c.drawRect(left, top, right, bottom, mColorPaint); } top = child.getBottom() + params.bottomMargin; bottom = top + mDividerHight; } else { top = child.getBottom() + params.bottomMargin; bottom = top + mDividerHight; } //畫分割線 mDividerDarwable.setBounds(left, top, right, bottom); mDividerDarwable.draw(c); if (mColorPaint != null) { c.drawRect(left, top, right, bottom, mColorPaint); } } } }
4. Adapter
public class MyRecycleViewAdapter extends RecyclerView.Adapter<MyRecycleViewAdapter.MyViewHolder> { private LayoutInflater mLayoutInflater; private List<String> mDataList; private int mItemLayout; public MyRecycleViewAdapter(Context context, int itemLayout, List<String> datalist) { mLayoutInflater = LayoutInflater.from(context); mItemLayout = itemLayout; mDataList = datalist; } @Override public MyRecycleViewAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new MyViewHolder(mLayoutInflater.inflate(mItemLayout, parent, false)); } @Override public void onBindViewHolder(MyRecycleViewAdapter.MyViewHolder holder, int position) { holder.mTextView.setText(mDataList.get(position)); } @Override public int getItemCount() { return mDataList.size(); } class MyViewHolder extends RecyclerView.ViewHolder { private TextView mTextView; public MyViewHolder(View itemView) { super(itemView); mTextView = (TextView) itemView.findViewById(R.id.tv); } } }
adapter 的item布局
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/tv" android:gravity="center" android:layout_width="match_parent" android:layout_height="60dp"/> </FrameLayout>
未完待續(xù)……
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android RecyclerView實(shí)現(xiàn)拼團(tuán)倒計(jì)時(shí)列表實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于Android RecyclerView實(shí)現(xiàn)拼團(tuán)倒計(jì)時(shí)列表的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)各位Android開(kāi)發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09Android通知欄前臺(tái)服務(wù)的實(shí)現(xiàn)
這篇文章主要介紹了Android通知欄前臺(tái)服務(wù)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03Android系統(tǒng)進(jìn)程間通信Binder機(jī)制在應(yīng)用程序框架層的Java接口源代碼分析
本文主要介紹 Android系統(tǒng)進(jìn)程間通信Binder機(jī)制Java 接口源碼分析,這里詳細(xì)介紹了如何實(shí)現(xiàn)Binder 機(jī)制和Java接口直接的通信,有興趣的小伙伴可以參考下2016-08-08Flutter?阻止系統(tǒng)鍵盤彈出的優(yōu)雅方式
這篇文章主要為大家介紹了Flutter?阻止系統(tǒng)鍵盤彈出的優(yōu)雅方式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11Android實(shí)現(xiàn)短信驗(yàn)證碼自動(dòng)攔截讀取功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)短信驗(yàn)證碼自動(dòng)攔截讀取功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-08-08Android 解決dialog彈出時(shí)無(wú)法捕捉Activity的back事件問(wèn)題
這篇文章主要介紹了Android 解決dialog彈出時(shí)無(wú)法捕捉Activity的back事件問(wèn)題的相關(guān)資料,需要的朋友可以參考下2016-11-11Android實(shí)現(xiàn)簡(jiǎn)易計(jì)步器功能隔天步數(shù)清零查看歷史運(yùn)動(dòng)紀(jì)錄
這篇文章主要介紹了Android實(shí)現(xiàn)簡(jiǎn)易計(jì)步器功能隔天步數(shù)清零查看歷史運(yùn)動(dòng)紀(jì)錄,需要的朋友可以參考下2017-06-06