android 自定義View刮刮樂
阿新 • • 發佈:2019-02-08
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("刮刮卡終於結束了");