自定義瓷磚效果的GridView

有時候需要給gridview加上分割線,沒有現成的解決方案,這裏寫好一個可以直接用的自定義gridview,就叫做LineGridView吧。先上圖,zaker客戶端第三方分享的gridview樣式:


可以看到靠邊的格子都是半封閉的,要實現這種效果僅僅靠美工給圖片恐怕不行。反編譯zaker的代碼,雖然看不到整個代碼,但是從中可以摸索出zaker是重寫了gridview的dispatchDraw實現的,知道了思路下面我就寫出了自己的實現方式。

我們都知道view有一個onDraw()方法,但是和dispatchDraw()有什麼區別呢?

繪製VIew本身的內容,通過調用View.onDraw(canvas)函數實現
繪製自己的孩子通過dispatchDraw(canvas)實現
View組件的繪製會調用draw(Canvas canvas)方法,draw過程中主要是先畫Drawable背景,對 drawable調用setBounds()然後是draw(Canvas c)方法.有點注意的是背景drawable的實際大小會影響view組件的大小,drawable的實際大小通過getIntrinsicWidth()和getIntrinsicHeight()獲取,當背景比較大時view組件大小等於背景drawable的大小
畫完背景後,draw過程會調用onDraw(Canvas canvas)方法,然後就是dispatchDraw(Canvas canvas)方法, dispatchDraw()主要是分發給子組件進行繪製,我們通常定製組件的時候重寫的是onDraw()方法。值得注意的是ViewGroup容器組件的繪製,當它沒有背景時直接調用的是dispatchDraw()方法, 而繞過了draw()方法,當它有背景的時候就調用draw()方法,而draw()方法裏包含了dispatchDraw()方法的調用。因此要在ViewGroup上繪製東西的時候往往重寫的是dispatchDraw()方法而不是onDraw()方法,或者自定製一個Drawable,重寫它的draw(Canvas c)和 getIntrinsicWidth(),
getIntrinsicHeight()方法,然後設爲背景。


知道了這些,下面我們就上代碼吧

package com.fanday.mobilesafe.view;

import com.fanday.mobilesafe.R;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.widget.GridView;

public class LineGridView extends GridView{
    public LineGridView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }
    public LineGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public LineGridView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    @Override
    protected void dispatchDraw(Canvas canvas){
        super.dispatchDraw(canvas);
        View localView1 = getChildAt(0);
        int column = getWidth() / localView1.getWidth();
        int childCount = getChildCount();
        Paint localPaint;
        localPaint = new Paint();
        localPaint.setStyle(Paint.Style.STROKE);
        localPaint.setColor(getContext().getResources().getColor(R.color.grid_line));
        for(int i = 0;i < childCount;i++){
            View cellView = getChildAt(i);
            if(i<column){
            	if(i==column-1){
            		canvas.drawLine(cellView.getLeft(), cellView.getBottom(), cellView.getRight(), cellView.getBottom(), localPaint);
                	canvas.drawLine(cellView.getLeft(), cellView.getTop(), cellView.getRight(), cellView.getTop(), localPaint);
                	continue;
            	}
            	canvas.drawLine(cellView.getLeft(), cellView.getBottom(), cellView.getRight(), cellView.getBottom(), localPaint);
            	canvas.drawLine(cellView.getLeft(), cellView.getTop(), cellView.getRight(), cellView.getTop(), localPaint);
            	canvas.drawLine(cellView.getRight(), cellView.getTop(), cellView.getRight(), cellView.getBottom(), localPaint);
            	}
            else{
            	if((i + 1) % column == 0){
                    canvas.drawLine(cellView.getLeft(), cellView.getBottom(), cellView.getRight(), cellView.getBottom(), localPaint);
                }else if((i + 1) > (childCount - (childCount % column))){
                    canvas.drawLine(cellView.getRight(), cellView.getTop(), cellView.getRight(), cellView.getBottom(), localPaint);
                }else{
                    canvas.drawLine(cellView.getRight(), cellView.getTop(), cellView.getRight(), cellView.getBottom(), localPaint);
                    canvas.drawLine(cellView.getLeft(), cellView.getBottom(), cellView.getRight(), cellView.getBottom(), localPaint);
                }
            }
            
        }
    }
}
這樣我們就實現了這種效果了,另外gridView點擊時的默認效果是不是有點醜,怎麼改呢

只需要給它的條目設置一個selector,點擊時更改一下背景顏色就ok了

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
	<!-- 點擊時調用 -->
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <gradient android:angle="270" android:endColor="#f00" android:startColor="#00f" />
        </shape>
    </item>
    <!-- 獲取焦點時調用 -->
    <item android:state_focused="true">
        <shape android:shape="rectangle">
            <!-- 給背景顏色設置一個漸變 -->
            <gradient android:angle="270.0" android:endColor="#f00" android:startColor="#00f" />

        </shape>
    </item>
    <!-- 默認狀態 -->
    <item>
        <shape android:shape="rectangle">
            <!-- 描邊,描出邊緣的線條 -->
            <!-- <stroke android:width="1.0px" android:color="@color/line" /> -->
        </shape>
   </item>
</selector>

把這個selector設置條目的背景就可以了
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章