自定義View學習之12/2

上一篇我們自定義學習畫了一個圓形等級條,並附帶延時線程完成動畫。
今天我們來弄個比較好玩的,(刮刮樂)。
首先先想好策略。
1、肯定是需要一張背景圖。
2、再是需要一張覆蓋在背景圖上面的灰色不透明圖塊。
3、當我們手指在灰色圖塊移動一次均會將路徑繪製到灰色不透明圖塊上,但是因爲繪製路徑是透明的,計算生成的混合圖像也會是透明的。所以我們會得到“橡皮擦”的效果。

好了。策略已想好,下面開始貼代碼。

private Bitmap fgBitmap, frontBitmap;// 前景橡皮擦的Bitmap和背景我們底圖的Bitmap

    private Canvas mCanvas;// 繪製橡皮擦路徑的畫布

    private Paint mPaint;// 橡皮檫路徑畫筆

    private Path mPath;// 橡皮擦繪製路徑

    private float x, y;

    public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomView(Context context) {
        super(context);
    }

    private void init() {
        // 實例化路徑對象
        mPath = new Path();

        // 實例化畫筆並開啓其抗鋸齒和抗抖動
        mPaint = new Paint();
        // 防鋸齒
        mPaint.setAntiAlias(true);
        // 防抖動
        mPaint.setDither(true);
        // 設置混合模式爲DST_IN
        mPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
        // 設置畫筆風格爲描邊
        mPaint.setStyle(Paint.Style.STROKE);
        // 設置路徑結合處樣式
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        // 設置筆觸類型
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        // 設置描邊寬度
        mPaint.setStrokeWidth(50);

        // 生成前景圖Bitmap 這裏拿的寬高要在onDraw裏面才能拿到哦。
        fgBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_4444);
        // 拿到灰色背景圖
        frontBitmap = CreateBitmap(Color.GRAY, getWidth(), getHeight());

        // 將其注入畫布
        mCanvas = new Canvas(fgBitmap);
        // 繪製灰色背景圖
        mCanvas.drawBitmap(frontBitmap, 0, 0, null);
    }
    /** 獲取傳入顏色,高端,寬度的Bitmap*/
    public Bitmap CreateBitmap(int color, int width, int height) {
        int[] rgb = new int[width * height];

        for (int i = 0; i < rgb.length; i++) {
            rgb[i] = color;
        }

        return Bitmap.createBitmap(rgb, width, height, Config.ARGB_8888);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mCanvas == null) {
            init();
        }
        // 繪製前景
        canvas.drawBitmap(fgBitmap, 0, 0, null);
        /*
         * 這裏要注意canvas和mCanvas是兩個不同的畫布對象
         * 當我們在屏幕上移動手指繪製路徑時會把路徑通過mCanvas繪製到fgBitmap上
         * 每當我們手指移動一次均會將路徑mPath作爲目標圖像繪製到mCanvas上,而在上面我們先在mCanvas上繪製了中性灰色
         * 兩者會因爲DST_IN模式的計算只顯示中性灰,但是因爲mPath的透明,計算生成的混合圖像也會是透明的
         * 所以我們會得到“橡皮擦”的效果
         */
        mCanvas.drawPath(mPath, mPaint);
        super.onDraw(canvas);
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        /*
         * 獲取當前事件位置座標
         */
        x = event.getX();
        y = event.getY();

        if (event.getAction() == MotionEvent.ACTION_DOWN) {// 手指接觸屏幕重置路徑
            mPath.reset();
            mPath.moveTo(x, y);
            // 重繪視圖
            invalidate();
            return true;
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {// 手指移動時連接路徑
            mPath.lineTo(x, y);
            // 重繪視圖
            invalidate();
            return true;
        }
        return super.onTouchEvent(event);
    }

xml佈局如下:
ImageView要跟自定義放一起哦,不然刮出來就沒內容了。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:layout_width="400dp"
        android:layout_height="400dp"  
        android:layout_centerInParent="true"
        android:src="@drawable/bb" />

    <com.customguaguale.CustomView
        android:id="@+id/CustomView_b"
        android:layout_width="400dp"
        android:layout_height="400dp"
        android:layout_centerInParent="true" />

</RelativeLayout>

效果圖如下:

這是塗刮層。嘿嘿趕緊動手刮刮吧,看看能刮出什麼來。。。

我刮我刮我刮刮刮刮刮……………………..

這裏寫圖片描述

刮出了個美女…..好白好嫩……..是我女朋友多好。。。。。

咳。。。。。。。好吧,我承認我想多了。。

歡迎大家指正錯誤,以及更優化方案。
下面是源碼地址:(http://download.csdn.net/detail/u013895206/8437885

未完待續。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章