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;
//繪制顏色分割線的畫(huà)筆
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);
//畫(huà)水平和垂直分割線
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;
}
//畫(huà)分割線
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);
//畫(huà)水平和垂直分割線
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;
}
//畫(huà)分割線
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;
}
//畫(huà)分割線
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)不固定刻度的刻度尺
這篇文章主要為大家詳細(xì)介紹了Android自定義RecyclerView實(shí)現(xiàn)不固定刻度的刻度尺,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07
android源碼探索之定制android關(guān)機(jī)界面的方法
這篇文章主要介紹了android源碼探索之定制android關(guān)機(jī)界面的方法,較為詳細(xì)的分析了Android關(guān)機(jī)界面的相關(guān)原理與代碼實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10
android的ListView點(diǎn)擊item使item展開(kāi)的做法的實(shí)現(xiàn)代碼
這篇文章主要介紹了android的ListView點(diǎn)擊item使item展開(kāi)的做法的實(shí)現(xiàn)代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12
Android 中LayoutInflater.inflate()方法的介紹
這篇文章主要介紹了Android 中LayoutInflater.inflate()方法的介紹的相關(guān)資料,希望通過(guò)本文大家能掌握這部分內(nèi)容,需要的朋友可以參考下2017-09-09
Android編程實(shí)現(xiàn)禁止StatusBar下拉的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)禁止StatusBar下拉的方法,涉及Android StatusBarManager相關(guān)屬性控制操作技巧,需要的朋友可以參考下2017-08-08
flutter FadeTransition實(shí)現(xiàn)透明度漸變動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了flutter FadeTransition實(shí)現(xiàn)透明度漸變動(dòng)畫(huà),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
Android沉浸式狀態(tài)欄實(shí)現(xiàn)示例
本篇文章主要介紹了Android沉浸式狀態(tài)欄實(shí)現(xiàn)示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02
Android制作登錄頁(yè)面并且記住賬號(hào)密碼功能的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android制作登錄頁(yè)面并且記住賬號(hào)密碼功能的實(shí)現(xiàn)代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04
Android控件之SlidingDrawer(滑動(dòng)式抽屜)詳解與實(shí)例分享
這篇文章詳細(xì)介紹了Android控件之SlidingDrawer(滑動(dòng)式抽屜)與實(shí)例,有需要的朋友可以參考一下2013-10-10
Android GZip的使用-開(kāi)發(fā)中網(wǎng)絡(luò)請(qǐng)求的壓縮實(shí)例詳解
這篇文章主要介紹了Android GZip的使用-開(kāi)發(fā)中網(wǎng)絡(luò)請(qǐng)求的壓縮實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2016-11-11

