1. 程式人生 > >android 自定義View刮刮樂

android 自定義View刮刮樂

public class GuaGuaView extends View {
    private String mText;
    private Rect mTextRect;
    private Paint mTextPaint;
    private int mTextSize;
    private int mTextColor;

    private Paint mTopPaint;
    private Bitmap topBitmap;
    private Canvas mCanvas;

    //手指的路徑
    private Path mPath;
    //手指上次停留的位置
private float mLastX; private float mLastY; private volatile boolean mIsComplete = false; private OnGuaGuaCompleteListener onGuaGuaCompleteListener; private PorterDuffXfermode porterDuffXfermode; public void setOnGuaGuaCompleteListener(OnGuaGuaCompleteListener onGuaGuaCompleteListener) { this
.onGuaGuaCompleteListener = onGuaGuaCompleteListener; } /** * 擡起手指時,若刮開區域大於閾值,給使用者提示 */ public interface OnGuaGuaCompleteListener { void onComplete(); } public GuaGuaView(Context context) { this(context, null); } public GuaGuaView(Context context, AttributeSet attrs) { this
(context, attrs, 0); } public GuaGuaView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); TypedArray typedArray = null; try { typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.GuaGuaView, defStyleAttr, 0); int indexCount = typedArray.getIndexCount(); for (int i = 0; i < indexCount; i++) { int attr = typedArray.getIndex(i); switch (attr) { case R.styleable.GuaGuaView_text: mText = typedArray.getString(attr); break; case R.styleable.GuaGuaView_textSize: //22sp轉化為畫素值 mTextSize = (int) typedArray.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 22, getResources().getDisplayMetrics())); break; case R.styleable.GuaGuaView_textColor: mTextColor = typedArray.getColor(attr, 0x000000); break; } } mTextPaint.setColor(mTextColor); mTextPaint.setTextSize(mTextSize); } finally { if (typedArray != null) typedArray.recycle(); } } private void init() { porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT); mText = "謝謝惠顧"; mTextRect = new Rect(); mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 22, getResources().getDisplayMetrics()); mTextPaint.setStyle(Paint.Style.STROKE); mTopPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTopPaint.setColor(Color.parseColor("#c0c0c0")); mTopPaint.setStyle(Paint.Style.FILL); mTopPaint.setDither(true); mTopPaint.setStrokeCap(Paint.Cap.ROUND); mTopPaint.setStrokeJoin(Paint.Join.ROUND); mTopPaint.setStrokeWidth(30); mPath = new Path(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //獲得文字的邊界資訊 mTextPaint.getTextBounds(mText, 0, mText.length(), mTextRect); canvas.drawText(mText, getWidth() / 2 - mTextRect.width() / 2, getHeight() / 2 + mTextRect.height() / 2, mTextPaint); if (!mIsComplete) { mTopPaint.setStyle(Paint.Style.STROKE); //只在源影象和目標影象相交的地方繪製透明 mTopPaint.setXfermode(porterDuffXfermode); mCanvas.drawPath(mPath, mTopPaint); //還原混合模式 mTopPaint.setXfermode(null); canvas.drawBitmap(topBitmap, 0, 0, null); } else { if (onGuaGuaCompleteListener != null) { onGuaGuaCompleteListener.onComplete(); } } } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mLastX = event.getX(); mLastY = event.getY(); mPath.moveTo(event.getX(), event.getY()); break; case MotionEvent.ACTION_MOVE: float dx = Math.abs(event.getX() - mLastX); float dy = Math.abs(event.getY() - mLastY); //手指移動的距離過小,不擦除 if (dx > 5 || dy > 5) { mLastX = event.getX(); mLastY = event.getY(); mPath.lineTo(mLastX, mLastY); } if (!mIsComplete) { invalidate(); } break; case MotionEvent.ACTION_UP: if (!mIsComplete) { new Thread(mRunnable).start(); } break; } return true; } private Runnable mRunnable = new Runnable() { @Override public void run() { int width = getWidth(); int height = getHeight(); int[] pixels = new int[width * height]; float wipeArea = 0; float totalArea = width * height; /** * getPixels()函式把一張圖片,從指定的偏移位置(offset),指定的位置(x,y)擷取指定的寬高(width,height) * 把所得影象的每個畫素顏色轉為int值,存入pixels。 * stride 引數指定在行之間跳過的畫素的數目。圖片是二維的,存入一個一維陣列中,那麼就需要這個引數來指定多少個畫素換一行。 * 詳見:http://blog.csdn.net/xx326664162/article/details/52240795 */ topBitmap.getPixels(pixels, 0, width, 0, 0, width, height); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { int index = i + j * width; if (pixels[index] == 0) { wipeArea++; } } } float progress = wipeArea / totalArea; Log.d("test", "progress-----" + progress); if (progress > 0.6) { mIsComplete = true; postInvalidate(); } } }; @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); topBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(topBitmap); Bitmap bottomBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.fg_guaguaka); //將圖片以合適比例顯示 //先畫灰色背景,再畫圖片 mCanvas.drawRoundRect(new RectF(0, 0, w, h), 50, 50, mTopPaint); /** * bitmap 要繪製的點陣圖物件 * src 要裁切的位置,若是null則顯示整張圖片 * dst 裁切後的圖片顯示的區域 * paint 畫筆 */ mCanvas.drawBitmap(bottomBitmap, null, new RectF(0, 0, w, h), null); } //設定中獎資訊 public void setText(String mText) { this.mText = mText; } }

attr.xml

<declare-styleable name="GuaGuaView">
        <attr name="text" format="string" />
        <attr name="textColor" format="color" />
        <attr name="textSize" format="dimension" />
    </declare-styleable>

使用:

<com.sign.signview.view.GuaGuaView
        android:id="@+id/guagua"
        android:layout_width="300dp"
        android:layout_height="100dp"
        android:layout_centerInParent="true"
        sign:text="我中獎了"
        sign:textColor="#ff0000"
        sign:textSize="22sp" />

guaGuaView.setOnGuaGuaCompleteListener(new GuaGuaView.OnGuaGuaCompleteListener() {
            @Override
            public void onComplete() {
                Toast.makeText(GuaGuaActivity.this, "恭喜你,沒中獎!", Toast.LENGTH_SHORT).show();
            }
        });
        guaGuaView.setText("刮刮卡終於結束了");