Android Project Scratch award details (iii)
Objective
In the previous issue we have completed the basic function of scraping card, this issue is to add a function to our project and beautify
Goal
We need a thread to complete our compute pixel, because the calculation cannot be performed in the UI thread all the time, it may stutter, and when the user lifts his finger, we start the calculation process to calculate the pixel that the user erased.
This function is somewhat complex, want to understand, need to know UI thread update view knowledge and Java process part of knowledge, recommend to see this handouts process update UI
Private Runnable mRunnable = new Runnable() {
Int[] pixels;
@Override
Public void run() {
Int w = mBitmap.getWidth();
Int h = mBitmap.getHeight();
Float wipeArea = 0; / / erase pixel count, initially 0
Float totalArea = w * h;//all pixels
Pixels = new int[w * h];
/**
* pixels receives an array of bitmap color values
* offset The first pixel index value written to pixels[]
* The line spacing in stride pixels[] is a number (must be greater than or equal to the width of the bitmap). Can be negative
* x The x coordinate value of the first pixel read from the bitmap.
* y y-coordinate value of the first pixel read from the bitmap
* width pixel width read from each line
* height the number of rows read
*/
Bitmap b = mBitmap;
b.getPixels(pixels, 0, w, 0, 0, w, h);
//for loop finds the pixel that the user erased, 0 is erase, wipeArea+1
For (int i = 0; i < totalArea; i++) {
If (pixels[i] == 0) {
wipeArea++;
}
}
//
If (wipeArea > 0 && totalArea > 0) {
Int percent = (int) (wipeArea * 100 / totalArea); / / calculation ratio
If (percent > 50) {
isClear = true; / / isClear is the previously declared global variable,
postInvalidate();//This method is called in the child process to redraw the View
}
}
}
};
There is a for loop in the above code to record the erase pixel point, some doubt, because the Yang big God uses the different, the hung Yang God is using the following nested loop
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
int index = i + j * w;
if (pixels[index] == 0) {
wipeArea++;
}
}
}
And then we need to rewrite the code, first of all, to add our actions to the user lifting the finger in the touch event.
case MotionEvent.ACTION_UP:
new Thread(mRunnable).start();
break;
Then, by isclear this variable to control whether to draw the path, theonDrawmethod to make such a modification
protected void onDraw(Canvas canvas) {
canvas.drawText(message,mBitmap.getWidth()/2-mBackground.width()/2,getMeasuredHeight()/2+mBackground.height()/2,messagePaint);
if (!isClear){
drawPath();
canvas.drawBitmap(mBitmap, 0,0, null);
}
}
When Canvas writes out text, it does not draw a cover layer, so that it achieves the effect of removing the cover layer.
Here you need to pay attention to if the conditions , but also toisClearuse thevolatiledecoration, popular is to add a lock to prevent concurrency errors
2. Masking layers Drawing Pictures
Perhaps everyone to this function very disdain, think oneself before not will, in fact, not so simple, I myself try when all appeared error, after searching data try to achieve effect.
First of all, I have a problem.
- Only part of the picture is displayed
- Brushes can not clear the picture, when the painting appears black handwriting
First, we can solve the problem by bitmap static method.
public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight,boolean filter)
Pass in a bitmap object that needs to be resized, followed by length and height, and the last parameter passed in true
Background = Bitmap.createscaledbitmap (background,width,height,true);//Zoom to Bitmap
The second problem, because we're using a double-buffered technical drawing, so we need to draw the overlay's picture first in the Mbitmap.
Mbitmap = Bitmap.createbitmap (width, height, Bitmap.Config.ARGB_8888);//Create a 32-bit Bitmap with the obtained width and height
Mcanvas = new Canvas (MBITMAP);
Mcanvas.drawbitamap (Background,0,0,null);
3. Callback Interface
public interface onGuaCompleteListener{
void complete();
}
private onGuaCompleteListener mlistener;
public void setGuaCompleteListener(onGuaCompleteListener mlistener) {
this.mlistener = mlistener;
}
Then add a callback to theonDrawmethod.
protected void onDraw(Canvas canvas) {
Log.d(TAG, "onDraw: draw");
canvas.drawText(message,mBitmap.getWidth()/2-mBackground.width()/2,getMeasuredHeight()/2+mBackground.height()/2,messagePaint);
if (!isClear){
drawPath();
canvas.drawBitmap(mBitmap, 0,0, null);
}else if (mlistener!=null){
mlistener.complete();
}
}
When the 60 is drawn, the value of Isclear is changed to true, and then it is entered into the else if, the callback completes the Scraping award interface
We set the listener in mainactivity to listen for the scratch card, pop a toast or a dialog box, and I'll just pop up a toast here for the sake of simplicity.
GuajiangView mView = (GuajiangView) findViewById(R.id.view);
mView.setGuaCompleteListener(new GuajiangView.onGuaCompleteListener() {
@Override
public void complete() {
Toast.makeText(MainActivity.this, "hello", Toast.LENGTH_SHORT).show();
}
});
Test diagram