1. 程式人生 > >RecyclerView中利用GridLayoutManager實現item四周都帶有分割線效果(更正版!!!)

RecyclerView中利用GridLayoutManager實現item四周都帶有分割線效果(更正版!!!)

今天,花了很長的時間才實現瞭如題的效果,回想一下,實現起來確實不難,只怪當時做的時候思路不清晰,沒想好就動手了,這是病,得改!好了,不多說,實現工程中主要參考了鴻洋部落格中Android RecyclerView 使用完全解析 體驗藝術般的控制元件DividerGridItemDecoration這個類的實現,其中有一個問題,就是一開始我死活都弄不出豎向方向分割線效果,後來查了一下資料,最後在部落格下方的評論那裡找到了解決方案,即是:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<gradient android:centerColor="#ff00ff00" android:endColor="#ff0000ff" android:startColor="#ffff0000" android:type="linear" /> <size android:height="4dp" android:width="4dp"/> </shape>

drawable檔案中需要加上android:width=”4dp”這個屬性,我在部落格上面沒看到有width這個屬性,可能部落格的demo裡面有吧(這,就尷尬了,我這次沒有下載原始碼來跑)。。
現在說一下如何實現item四周都帶有分割線效果,關鍵地方在於DividerGridItemDecoration這個類,其中我作了修改的地方主要如下:

    public void drawHorizontal(Canvas c, RecyclerView parent)
    {
        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
left = child.getLeft() - params.leftMargin; final int right = child.getRight() + params.rightMargin + mDivider.getIntrinsicWidth(); int top = 0; int bottom = 0; // 1 不計算中間item的divider情況 if((i/column_num) == 0) { //畫item最上面的分割線 top = child.getTop(); //該處一開始是top = 0,沒考慮到佈局中recyclerview的padding情況 bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); //畫item下面的分割線 top = child.getBottom() + params.bottomMargin; bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } else { top = child.getBottom() + params.bottomMargin; bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } // 2 計算中間item的divider情況 // //畫item最上面的分割線 // top = child.getTop(); //該處一開始是top = 0,沒考慮到佈局中recyclerview的padding情況 // bottom = top + mDivider.getIntrinsicHeight(); // mDivider.setBounds(left, top, right, bottom); // mDivider.draw(c); // //畫item下面的分割線 // top = child.getBottom() + params.bottomMargin; // bottom = top + mDivider.getIntrinsicHeight(); // mDivider.setBounds(left, top, right, bottom); // mDivider.draw(c); } } public void drawVertical(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; // 3 不計算中間item的divider情況 if((i%column_num) == 0) { //item左邊分割線 left = child.getLeft();//該處一開始是left = 0,沒考慮到佈局中recyclerview的padding情況 right = left + mDivider.getIntrinsicWidth(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); //item右邊分割線 left = child.getRight() + params.rightMargin; right = left + mDivider.getIntrinsicWidth(); } else { left = child.getRight() + params.rightMargin; right = left + mDivider.getIntrinsicWidth(); } // 4 計算中間item的divider情況 // //item左邊分割線 // left = child.getLeft();//該處一開始是left = 0, 沒考慮到佈局中recyclerview的padding情況 // right = left + mDivider.getIntrinsicWidth(); // mDivider.setBounds(left, top, right, bottom); // mDivider.draw(c); // //item右邊分割線 // left = child.getRight() + params.rightMargin; // right = left + mDivider.getIntrinsicWidth(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } }

程式碼裡面我已經加上相應的註釋,相信還是比較容易理解的,另外,遮蔽瞭如下的程式碼(下面的程式碼判斷是否是最後一列,博主原本是不繪製右邊的分割線):

private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
                                int childCount)
    {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager)
        {
/*            if ((pos + 1) % spanCount == 0)// 如果是最後一列,則不需要繪製右邊
            {
                return true;
            }*/
        } else if (layoutManager instanceof StaggeredGridLayoutManager)
        {

下面是判斷是否是最後一行,博主原本是不繪製底部分割線

    private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
                              int childCount)
    {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager)
        {
/*             childCount = childCount - childCount % spanCount;
           if (pos >= childCount)// 如果是最後一行,則不需要繪製底部
                return true;*/
        } else if (layoutManager instanceof StaggeredGridLayoutManager)
        {

實現的效果圖,請忽視分割線太過花俏。。

備註:顯示效果中出現了中間的item正常,但是邊緣的item寬高彆扭,主要是因為 我沒有處理中間item的左、右divider造成,因為我的divider_bg中divider的width、height設定的比較小,不處理中間item的左、右divider看上去稍微好看些,實際開發中,如果要處理,那麼恢復 drawHorizontal方法中的2註釋(還要註釋掉1註釋)以及 drawVertical方法中的4註釋(還要註釋掉3註釋),可詳見demo

嗯,以上就是主要的修改程式碼,下面附上demo下載連結,點我下載~