Android實(shí)現(xiàn)刮刮樂示例分析
微信公眾號(hào)有很多都做刮刮樂的活動(dòng),本文就實(shí)現(xiàn)了刮刮樂的效果,具體代碼如下:
首先要做一個(gè)類似橡皮擦的東西吧,然后才能把紙上的筆跡擦除
/**
* FileName: SplashActivity.java
*
* @desc 橡皮擦功能,類似刮刮樂效果
* @author HTP
* @Date 20140311
* @version 1.00
*/
public class Text_Rubbler extends TextView {
private float TOUCH_TOLERANCE; // 填充距離,使線條更自然,柔和,值越小,越柔和。
// private final int bgColor;
// 位圖
private Bitmap mBitmap;
// 畫布
private Canvas mCanvas;
// 畫筆
private Paint mPaint;
private Path mPath;
private float mX, mY;
private boolean isDraw = false;
public Text_Rubbler(Context context) {
/**
* @param context 上下文
*/
super(context);
}
public Text_Rubbler(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// bgColor =
// attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android",
// "textColor", 0xFFFFFF);
// System.out.println("Color:"+bgColor);
}
public Text_Rubbler(Context context, AttributeSet attrs) {
super(context, attrs);
// bgColor =
// attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android",
// "textColor", 0xFFFFFF);
// System.out.println(bgColor);
// System.out.println(attrs.getAttributeValue("http://schemas.android.com/apk/res/android",
// "layout_width"));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isDraw) {
mCanvas.drawPath(mPath, mPaint);
// mCanvas.drawPoint(mX, mY, mPaint);
canvas.drawBitmap(mBitmap, 0, 0, null);
}
}
/**
* 開啟檫除功能
*
* @param bgColor
* 覆蓋的背景顏色
* @param paintStrokeWidth
* 觸點(diǎn)(橡皮)寬度
* @param touchTolerance
* 填充距離,值越小,越柔和。
*/
public void beginRubbler(final int bgColor, final int paintStrokeWidth,
float touchTolerance) {
TOUCH_TOLERANCE = touchTolerance;
// 設(shè)置畫筆
mPaint = new Paint();
// mPaint.setAlpha(0);
// 畫筆劃過的痕跡就變成透明色了
mPaint.setColor(Color.BLACK); // 此處不能為透明色
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
// 或者
// mPaint.setAlpha(0);
// mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND); // 前圓角
mPaint.setStrokeCap(Paint.Cap.ROUND); // 后圓角
mPaint.setStrokeWidth(paintStrokeWidth); // 筆寬
// 痕跡
mPath = new Path();
;
// 覆蓋
// if (getLayoutParams().width == LayoutParams.FILL_PARENT) {
//
// }
mBitmap = Bitmap.createBitmap(getLayoutParams().width,
getLayoutParams().height, Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mCanvas.drawColor(bgColor);
isDraw = true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isDraw) {
return true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: // 觸點(diǎn)按下
// touchDown(event.getRawX(),event.getRawY());
touchDown(event.getX(), event.getY());
invalidate();
break;
case MotionEvent.ACTION_MOVE: // 觸點(diǎn)移動(dòng)
touchMove(event.getX(), event.getY());
invalidate();
break;
case MotionEvent.ACTION_UP: // 觸點(diǎn)彈起
touchUp(event.getX(), event.getY());
invalidate();
break;
default:
break;
}
return true;
}
private void touchDown(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touchMove(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touchUp(float x, float y) {
mPath.lineTo(x, y);
mCanvas.drawPath(mPath, mPaint);
mPath.reset();
}
}
接下來就是使用橡皮檫擦除了
/**
* FileName: RubblerAct.java
* @Desc 該類通過調(diào)用Text_Rubbler這個(gè)類將在Activity上顯示一片刮一刮的區(qū)域,可以出發(fā)觸摸事件
* @author HTP
* @Date 20140312
* @version 1.00
*/
public class RubblerAct extends Activity {
// 刮開后文字顯示
private TextView tv_rubbler;
// 得到刮一刮的內(nèi)容
private Sentence mSentence;
// 下一張
private TextView tv_next;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(new Rubble(this,"謝謝惠顧",new Rect(100, 200,
// 300,250),2,1f,14));
// /////////////////////////////////////////
setContentView(R.layout.rubbler);
// 設(shè)置的顏色必須要有透明度。
((Text_Rubbler) findViewById(R.id.rubbler)).beginRubbler(0xFFFFFFFF, 20,
1f);// 設(shè)置橡皮擦的寬度等
mSentence = new Sentence();
// 隨機(jī)初始化文字
tv_rubbler = (TextView) findViewById(R.id.rubbler);
String str = mSentence.getSentence();
tv_rubbler.setText(str);
tv_next = (TextView) findViewById(R.id.tv_next);
// 點(diǎn)擊下一步
tv_next.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
String str = mSentence.getSentence();
tv_rubbler.setText(str);
((Text_Rubbler) findViewById(R.id.rubbler))// 初始化狀態(tài)
.beginRubbler(0xFFFFFFFF, 20, 1f);
}
});
}
class Rubble extends View {
private final int PAINT_STROKE_WIDTH;
private final float TOUCH_TOLERANCE; // 填充距離,使線條更自然,柔和,值越小,越柔和。
private final int TEXT_SIZE;
private Bitmap mBitmap;
// 畫布
private Canvas mCanvas;
// 畫筆
private Paint mPaint;
private Path mPath;
private float mX, mY;
private final int X, Y, W, H;
private final Rect touchRect;
public Rubble(Context context, String bgText, Rect rect,
int paintStrokeWidth, float touchTolerance, int textSize) {
super(context);
setFocusable(true);
touchRect = rect;
W = rect.right - rect.left;
H = rect.bottom - rect.top;
X = rect.left;
Y = rect.top;
TEXT_SIZE = textSize;
PAINT_STROKE_WIDTH = paintStrokeWidth;
TOUCH_TOLERANCE = touchTolerance;
setBackground(touchRect, bgText);
initDrowTools();
}
private void setBackground(Rect rect, String bgText) {
DisplayMetrics dm = new DisplayMetrics();
dm = this.getResources().getDisplayMetrics();
Bitmap bitmap = Bitmap.createBitmap(dm.widthPixels,
dm.heightPixels, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(0x88000000);
// paint.setStyle(Style.STROKE);
// paint.setTextAlign(Align.CENTER);
paint.setTextSize(TEXT_SIZE);
// paint.setTextScaleX(1.5f);
canvas.drawColor(Color.WHITE);
// 畫字的坐標(biāo)不好控制
int x = rect.left
+ (rect.right - rect.left - bgText.length() * TEXT_SIZE)
/ 2;
int y = rect.top + (rect.bottom - rect.top - TEXT_SIZE) / 2;
// int y = 218+25;
canvas.drawText(bgText, x, y, paint);
Drawable drawable = new BitmapDrawable(bitmap);
setBackgroundDrawable(drawable);
}
private void initDrowTools() {
// 設(shè)置畫筆
mPaint = new Paint();
// mPaint.setAlpha(0);
// 畫筆劃過的痕跡就變成透明色了
mPaint.setColor(Color.BLACK); // 此處不能為透明色
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
// 或者
// mPaint.setAlpha(0);
// mPaint.setXfermode(new
// PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND); // 前圓角
mPaint.setStrokeCap(Paint.Cap.ROUND); // 后圓角
mPaint.setStrokeWidth(PAINT_STROKE_WIDTH); // 筆寬
// 痕跡
mPath = new Path();
;
// 覆蓋
mBitmap = Bitmap.createBitmap(W, H, Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mCanvas.drawColor(0x88000000);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mCanvas.drawPath(mPath, mPaint);
// mCanvas.drawPoint(mX, mY, mPaint);
canvas.drawBitmap(mBitmap, X, Y, null);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
System.out.print("X--" + event.getX());
System.out.println("Y--" + event.getY());
if (!touchRect.contains((int) event.getX(), (int) event.getY())) {
return false;
}
switch (event.getAction()) {
// 觸點(diǎn)按下
case MotionEvent.ACTION_DOWN: {
touchDown(event.getRawX(), event.getRawY());
touchDown(event.getX() - touchRect.left, event.getY()
- touchRect.top);
invalidate();
break;
}
case MotionEvent.ACTION_MOVE: // 觸點(diǎn)移動(dòng)
touchMove(event.getX() - touchRect.left, event.getY()
- touchRect.top);
invalidate();
break;
case MotionEvent.ACTION_UP: // 觸點(diǎn)彈起
touchUp(event.getX() - touchRect.left, event.getY()
- touchRect.top);
invalidate();
break;
default:
break;
}
return true;
}
private void touchDown(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touchMove(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touchUp(float x, float y) {
mPath.lineTo(x, y);
mCanvas.drawPath(mPath, mPaint);
mPath.reset();
}
}
/**
* 鍵盤事件,當(dāng)按下back鍵的時(shí)候詢問是否再按一次退出程序
*/
// 退出時(shí)間
private long exitTime = 0;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK
&& event.getAction() == KeyEvent.ACTION_DOWN) {
if ((System.currentTimeMillis() - exitTime) > 2000) {
Toast.makeText(getApplicationContext(), "再按一次退出程序",
Toast.LENGTH_SHORT).show();
exitTime = System.currentTimeMillis();
} else {
finish();
System.exit(0);
}
return true;
}
return super.onKeyDown(keyCode, event);
}
}
實(shí)現(xiàn)效果如下:

感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
Android 詳解自定義圓角輸入框和按鈕的實(shí)現(xiàn)流程
對(duì)于安卓程序員來說,自定義view簡(jiǎn)直不要太重要,畢竟有很多功能,譬如圓形頭像這些,用單純的原生非常難以實(shí)現(xiàn),而用自定義view,簡(jiǎn)直分分鐘,今天我們來實(shí)現(xiàn)自定義圓角輸入框和按鈕,大家可以跟著練習(xí),掌握技巧2021-11-11
Android Studio創(chuàng)建AIDL文件并實(shí)現(xiàn)進(jìn)程間通訊實(shí)例
本篇文章主要介紹了Android Studio創(chuàng)建AIDL文件并實(shí)現(xiàn)進(jìn)程間通訊實(shí)例,具有一定的參考價(jià)值,有興趣可以了解一下。2017-04-04
Android 中CheckBox的isChecked的使用實(shí)例詳解
這篇文章主要介紹了Android 中CheckBox的isChecked的使用實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-04-04
Android Jetpack架構(gòu)組件Lifecycle詳解
這篇文章主要介紹了Android Jetpack架構(gòu)組件Lifecycle詳解,Lifecycle是Jetpack架構(gòu)組件中用來感知生命周期的組件,使用Lifecycles可以幫助我們寫出和生命周期相關(guān)更簡(jiǎn)潔更易維護(hù)的代碼。對(duì)此感興趣的小伙伴可以來學(xué)習(xí)一下2020-07-07
android 使用OkHttp上傳多張圖片的實(shí)現(xiàn)代碼
這篇文章主要介紹了android 使用OkHttp上傳多張圖片的相關(guān)資料,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-07-07
Android應(yīng)用開發(fā)中自定義ViewGroup的究極攻略
這里我們要演示的自定義ViewGroup中將實(shí)現(xiàn)多種方式排列和滑動(dòng)等效果,并且涵蓋子View之間Touch Event的攔截與處理等問題,完全干貨,下面就為大家送上Android應(yīng)用開發(fā)中自定義ViewGroup的究極實(shí)例攻略2016-05-05
詳解Android中Glide與CircleImageView加載圓形圖片的問題
本篇文章主要介紹了詳解Android中Glide與CircleImageView加載圓形圖片的問題,具有一定的參考價(jià)值,有興趣的可以了解一下2017-09-09

