編輯:關於Android編程
直接上效果圖
功能特色:
1、可以設置刮開後顯示文字或圖片
2、可以統計已刮開區域所占百分比
下面是源碼:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+PC9wPgo8cHJlIGNsYXNzPQ=="brush:java;">@SuppressLint("HandlerLeak")
public class RubberView extends TextView {
private static final int W = 480;
private static final int H = 800;
private static final int MV = 1;
private static final int SW = 50;
private static final int MC = 0xFFD6D6D6;
private int mWidth;
private int mHeight;
private int mMaskColor;
private int mStrokeWidth;
private float mX;
private float mY;
private boolean mRun;
private boolean caculate;
private Path mPath;
private Paint mPaint;
private Paint mBitmapPaint;
private Canvas mCanvas;
private Bitmap mBitmap;
private int[] mPixels;
private Thread mThread;
private onWipeListener mWipeListener;
public RubberView(Context context) {
super(context);
init(context);
}
public RubberView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private final void init(Context context) {
mMaskColor = MC;
mStrokeWidth = SW;
mPath = new Path();
mBitmapPaint = new Paint();
mPaint = new Paint();
mPaint.setAntiAlias(true);// 抗鋸齒
mPaint.setDither(true);// 遞色
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND); // 前圓角
mPaint.setStrokeCap(Paint.Cap.ROUND); // 後圓角
mPaint.setStrokeWidth(mStrokeWidth); // 筆寬
mBitmap = Bitmap.createBitmap(W, H, Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mCanvas.drawColor(mMaskColor);
mRun = true;
mThread = new Thread(mRunnable);
mThread.start();
setGravity(Gravity.CENTER);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mCanvas.drawPath(mPath, mPaint);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int w = MeasureSpec.getSize(widthMeasureSpec);
int h = MeasureSpec.getSize(heightMeasureSpec);
if (w > 0 && h > 0) {
mWidth = w;
mHeight = h;
}
}
public void reset() {
mPath.reset();
mCanvas.drawPaint(mPaint);
mCanvas.drawColor(mMaskColor);
invalidate();
}
public void setOnWipeListener(onWipeListener listerer) {
this.mWipeListener = listerer;
}
public void setStrokeWidth(int width) {
this.mStrokeWidth = width;
mPaint.setStrokeWidth(width);
}
public void setMaskColor(int color) {
this.mMaskColor = color;
reset();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean invalidate = false;
boolean consume = false;
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
consume = true;
touchDown(event);
break;
case MotionEvent.ACTION_MOVE:
consume = true;
invalidate = touchMove(event);
break;
case MotionEvent.ACTION_UP:
consume = true;
touchUp(event);
break;
}
if (invalidate) {
invalidate();
}
if (consume) {
return true;
}
return super.onTouchEvent(event);
}
// 手指點下屏幕時調用
private void touchDown(MotionEvent event) {
caculate = false;
// 重置繪制路線,即隱藏之前繪制的軌跡
mPath.reset();
float x = event.getX();
float y = event.getY();
mX = x;
mY = y;
// mPath繪制的繪制起點
mPath.moveTo(x, y);
}
// 手指在屏幕上滑動時調用
private boolean touchMove(MotionEvent event) {
caculate = false;
final float x = event.getX();
final float y = event.getY();
final float previousX = mX;
final float previousY = mY;
// 設置貝塞爾曲線的操作點為起點和終點的一半
float cX = (x + previousX) / 2;
float cY = (y + previousY) / 2;
final float dx = Math.abs(x - previousX);
final float dy = Math.abs(y - previousY);
boolean move = false;
if (dx >= MV || dy >= MV) {
// 二次貝塞爾,實現平滑曲線;cX, cY為操作點 x,y為終點
mPath.quadTo(cX, cY, x, y);
// 第二次執行時,第一次結束調用的坐標值將作為第二次調用的初始坐標值
mX = x;
mY = y;
move = true;
}
return move;
}
private void touchUp(MotionEvent event) {
caculate = true;
mRun = true;
}
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
while (mRun) {
SystemClock.sleep(100);
// 收到計算命令,立即開始計算
if (caculate) {
caculate = false;
int w = mWidth;
int h = mHeight;
float wipeArea = 0;
float totalArea = w * h;
// 計算耗時100毫秒左右
Bitmap bitmap = mBitmap;
if (mPixels == null) {
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);
Message msg = mHandler.obtainMessage();
msg.what = 0x1;
msg.arg1 = percent;
mHandler.sendMessage(msg);
}
}
}
}
};
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
if (mWipeListener != null) {
int percent = msg.arg1;
mWipeListener.onWipe(percent);
}
};
};
public interface onWipeListener {
public void onWipe(int percent);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mRun = false;
}
}
Demo下載地址:
RubberDemo.rar
一、簡介上篇博客概括的介紹了硅谷商城項目的首頁技術要點。本篇內容給大家講解硅谷商城項目分類,分類頁面用的技術包括:采用FlycoTabLayout實現標簽和分類切換、布局
一、什麼是JNI: JNI是Java Native Interface的縮寫,中文為JAVA本地調用。從Java1.1開始,Java Native Interface
下面詳細解釋這四大方式的特點第一種:文件存儲數據核心原理: Context提供了兩個方法來打開數據文件裡的文件IO流 FileInputStream openFileIn
移植Android到不同的設備 Android允許提供不同的硬件平台和驅動支持Android的運行。硬件抽象層(Hardware Abstraction Layer)