Android刮刮卡自定義控件

網上的都是自己繪製的或者圖片,我的需求是可以隨意的自定義底部和頂部的佈局。所以自己重寫一個,原理就是直接繼承 View 來實現一個刮層,讓這個刮層和圖片以及文字不產生任何依賴,再結合 FrameLayout 將刮層放置最上一層,刮層之下你想放多少圖片文字,圖片文字要怎麼佈局擺放都行。由於是FrameLayout ,刮層的上面想加內容都是可以的。如圖:

 

 

原理:刮刮卡無非就是文本,或者圖片,就是我們下邊的佈局,然後在其上繪製刮獎層,設置DST_OUT,然後把用戶觸摸繪製上去;這樣消失以後就能看到背後的獎了。

佈局

1
2
3
4
5
6
7
8
9
10
11
<FrameLayout
       android:layout_width="350dp"
       android:layout_centerInParent="true"
       android:layout_height="150dp">
       <include
           layout="@layout/scratch_view_after"/>
       <coordemo.ly.com.myapplication.GuaGuaKaView
           android:layout_width="match_parent"
           android:id="@+id/gg1"
           android:layout_height="match_parent" />
   </FrameLayout>

  

刮一刮控件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
public class GuaGuaKaView extends View {
    /**
     * 繪製線條的畫筆
     */
    private Paint mOutterPaint = new Paint();
    /**
     * 遮層畫筆
     */
    private Paint mMaskPaint = new Paint();
    /**
     * 最下面畫筆
     */
    private Paint mBackPint = new Paint();
    /**
     * mCanvas繪製內容在其上
     */
    private Bitmap mBitmap;
    /**
     * 記錄用戶繪製的Path
     */
    private Path mPath = new Path();
    /**
     * 內存中創建的Canvas
     */
    private Canvas mCanvas;
    private boolean isComplete;
    private Rect mTextBound = new Rect();
    private String mText = "¥500,0000";
    private int mLastX;
    private int mLastY;
    private int measuredWidth;
    private int measuredHeight;
    public GuaGuaKaView(Context context) {
        this(context, null);
    }
    public GuaGuaKaView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public GuaGuaKaView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }
    private void init() {
        mPath = new Path();
        setUpOutPaint();
        setUpBackPaint();
    }
    /**
     * 初始化canvas的繪製用的畫筆
     */
    private void setUpBackPaint() {
        mBackPint.setStyle(Style.FILL);
        mBackPint.setTextScaleX(2f);
        mBackPint.setColor(Color.DKGRAY);
        mBackPint.setTextSize(32);
        mBackPint.getTextBounds(mText, 0, mText.length(), mTextBound);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        if (!isComplete) {
            drawPath();
            canvas.drawBitmap(mBitmap, 0, 0, null);
        } else {
            this.setVisibility(GONE);
        }
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        measuredWidth = getMeasuredWidth();//寬高和父view的相同
        measuredHeight = getMeasuredHeight();
        // 初始化bitmap
        mBitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
        mMaskPaint.setColor(Color.parseColor("#00000000"));//遮層透明
        mMaskPaint.setStyle(Style.FILL);
        mCanvas.drawRoundRect(new RectF(0, 0, measuredWidth, measuredHeight), 0, 0, mMaskPaint);
        mCanvas.drawBitmap(BitmapFactory.decodeResource(getResources(),
                R.drawable.award_1), null, new RectF(0, 0, measuredWidth, measuredHeight), null);//遮層
    }
    /**
     * 設置畫筆的一些參數
     */
    private void setUpOutPaint() {
        // 設置畫筆
//         mOutterPaint.setAlpha(0);
        mOutterPaint.setColor(Color.parseColor("#c0c0c0"));
        mOutterPaint.setAntiAlias(true);
        mOutterPaint.setDither(true);
        mOutterPaint.setStyle(Style.STROKE);
        mOutterPaint.setStrokeJoin(Paint.Join.ROUND); // 圓角
        mOutterPaint.setStrokeCap(Paint.Cap.ROUND); // 圓角
        // 設置畫筆寬度
        mOutterPaint.setStrokeWidth(50);
    }
    /**
     * 繪製線條
     */
    private void drawPath() {
        mOutterPaint.setStyle(Style.STROKE);
        mOutterPaint
                .setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));//取倆者的交集
        mCanvas.drawPath(mPath, mOutterPaint);
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mLastX = x;
                mLastY = y;
                mPath.moveTo(mLastX, mLastY);
                break;
            case MotionEvent.ACTION_MOVE:
                int dx = Math.abs(x - mLastX);
                int dy = Math.abs(y - mLastY);
                if (dx > 3 || dy > 3)
                    mPath.lineTo(x, y);
                mLastX = x;
                mLastY = y;
                new Thread(mRunnable).start();
                break;
            case MotionEvent.ACTION_UP:
                new Thread(mRunnable).start();
                break;
        }
        invalidate();
        return true;
    }
    /**
     * 統計擦除區域任務
     */
    private Runnable mRunnable = new Runnable() {
        private int[] mPixels;
        @Override
        public void run() {
            int w = getWidth();
            int h = getHeight();
            float wipeArea = 0;
            float totalArea = w * h;
            Bitmap bitmap = mBitmap;
            mPixels = new int[w * h];
            /**
             * 拿到所有的像素信息
             */
            bitmap.getPixels(mPixels, 0, w, 0, 0, w, h);
            /**
             * 遍歷統計擦除的區域
             */
            for (int i = 0; i < w; i++) {
                for (int j = 0; j < h; j++) {
                    int index = i + j * w;
                    if (mPixels[index] == 0) {
                        wipeArea++;
                    }
                }
            }
            /**
             * 根據所佔百分比,進行一些操作
             */
            if (wipeArea > 0 && totalArea > 0) {
                int percent = (int) (wipeArea * 100 / totalArea);
//                Log.e("TAG", percent + "");
                if (percent > 50) {
//                    Log.e("TAG", "清除區域達到50%,下面自動清除");
                    isComplete = true;
                    postInvalidate();
                }
            }
        }
    };
    /**
     * 將佈局轉換成bitmap
     * @param addViewContent
     * @return
     */
    private Bitmap getViewBitmap(View addViewContent) {
        addViewContent.setDrawingCacheEnabled(true);
        addViewContent.measure(
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        addViewContent.layout(0, 0,
                addViewContent.getMeasuredWidth(),
                addViewContent.getMeasuredHeight());
        addViewContent.buildDrawingCache();
        Bitmap cacheBitmap = addViewContent.getDrawingCache();
        Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
        return bitmap;
    }
}

  

 
GitHub地址:
發佈了6 篇原創文章 · 獲贊 2 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章