Android Project Scratch award detailed (ii)
Objective
In the previous issue we have implemented a simple scratch card function, this issue we will improve it
Goal
-
Change the width of the scratch award to the appropriate height and center the Scratch award position
In fact, it's very simple, we can change the size of layout directly, and use the modified position in the layout.gravity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context="com.wan.guajiang.MainActivity">
<com.wan.guajiang.GuaGuaKa
android:layout_width="300dp"
android:layout_height="100dp"/>
</LinearLayout>
-
Change the picture of the information layer into text
Before we draw the information layer is the winning picture, if there is no picture what to do? Of course, directly take the words to replace, canvas can not only draw pictures, but also can draw text, write text
First, let's look at the method parameters of the canvasdrawText
drawText(String text, float x, floaty, Paint paint);
Text even if you want to write the text content, X, Y is the location of the write, it should be noted that the X, Y coordinates here is not the upper left corner of the text, but a closer to the lower left corner of the position. It's probably here:
The last parameter is the brush, which is similar to the previous one, and will be added later.
We want to write the text in the middle of the information layer, the coordinates of x, y, how to write it? As you can know, the canvas uses thedrawTextmethod, XY coordinates are actually located in the lower left corner of the text, is the diagram
Believe this picture is still very well understood, we continue to start writing code
-
-
First of all, we need a text content
String message = "Congratulations on winning, 30,000 yuan!";
-
-
Define our brush paint and set it up
Here we need a rect rectangle to get the background size of the text content, which is the red rectangle in the paint brush, which provides a wayGettextbounds, which we can use to get the background size of the text content
Messagepaint.gettextbounds (String text,float start,float end, Rect rect);
The above code means to intercept the length of the text from start to end, to form a rectangle with the length of the intercept and the height of the text, and the rect rectangle to receive the rectangle
Rect mBackground = new Rect();// is used to receive the rectangle returned by getTextBounds
Paint messagePaint = new Paint();
messagePaint.setColor(Color.RED);
messagePaint.setAntiAlias(true);
messagePaint.setStyle(Paint.Style.STROKE);
messagePaint.getTextBounds(message,0,message.length(),mBackground);
messagePaint.setTextSize(30);
-
-
calculates x, y coordinates, Canvas uses DrawText to write out text
We have two ways to get the length and width of the black rectangle before, one is to use itgetMeasured, the other is to use itmBitmap.getto get the length and width
canvas.drawText(message,getMeasuredWidth()/2-mBackground.width()/2,getMeasuredHeight()/2+mBackground.height()/2,messagePaint);
Or:
canvas.drawText(message,mBitmap.getWidth()/2-mBackground.width()/2,mBitmap.getHeight()/2+mBackground.height()/2,messagePaint);
Test diagram
Full code
Public class GuajiangView extends View {
/**
* Paint the Paint of the line, that is, the user draws the Path
*/
Private Paint mOutterPaint = new Paint();
/**
* Record the path drawn by the user
*/
Private Path mPath = new Path();
/**
* Canvas created in memory
*/
Private Canvas mCanvas;
/**
* mCanvas draws content on it
*/
Private Bitmap mBitmap;
Private int mLastX;
Private int mLastY;
Private String message;//winning information
Private Rect mBackground;//text background rectangle size
Private Paint messagePaint = new Paint();//text brush
Private boolean isClear = false;
Public GuajiangView(Context context) {
Super(context);
}
Public GuajiangView(Context context, @Nullable AttributeSet attrs) {
Super(context, attrs);
}
Public GuajiangView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
Super(context, attrs, defStyleAttr);
}
Public GuajiangView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
Super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
Protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.d(TAG, "onMeasure: measurement");
Int width = getMeasuredWidth();
Int height = getMeasuredHeight();
/ / Initialize the bitmap
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);//Get the width and height to create a 32-bit bitmap
mCanvas = new Canvas(mBitmap);//Create a canvas with bitmap
mCanvas.drawColor(Color.GREEN);//Set the color of the canvas to green
mBackground = new Rect();
Message = "Congratulations on winning, 30,000 yuan!";
messagePaint.setColor(Color.RED);
messagePaint.setAntiAlias(true);
messagePaint.setStyle(Paint.Style.STROKE);
messagePaint.getTextBounds(message,0,message.length(),mBackground);
messagePaint.setTextSize(30);
// set the brush
mOutterPaint.setColor(Color.BLUE);
mOutterPaint.setAntiAlias(true);//With anti-aliasing, it consumes a lot of resources, drawing graphics will slow down
mOutterPaint.setDither(true);//Image dithering will make the drawn picture color smoother and fuller, and the image will be clearer
mOutterPaint.setStyle(Paint.Style.STROKE);
mOutterPaint.setStrokeJoin(Paint.Join.ROUND);//Rounding, smoothing
mOutterPaint.setStrokeCap(Paint.Cap.ROUND); //Rounding
mOutterPaint.setStrokeWidth(20); // Set the brush width
messagePaint.setColor(Color.RED);
}
@Override
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);
drawPath();
canvas.drawBitmap(mBitmap, 0,0, null);
}
Private void drawPath() {
Log.d(TAG, "drawPath: ");
mOutterPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
mCanvas.drawPath(mPath, mOutterPaint);
}
@Override
Public boolean onTouchEvent(MotionEvent event) {
//When the finger is pressed onto the screen, the Moveto method is used in the Path path, moving to the current position of the finger, invalidate to refresh the View, and callback the onDraw method (not yet drawn)
/ / After the finger moves, the action is in the state of ACTION_MOVE, the Path path uses the lineto method (draw a line),
// At the same time, the x,y coordinates are updated, invalidate refreshes the View, and the onDraw method is called back. The canvas draws the path using the brush through the drawpath. If the user does not raise the finger, then continue to loop the steps in ACTION_MOVE.
Int action = event.getAction();
Int x = (int) event.getX();//Get the x coordinate
Int y = (int) event.getY();//Get the y coordinate
Switch (action){
Case MotionEvent.ACTION_DOWN:
mLastX = x;
mLastY = y;
mPath.moveTo(mLastX, mLastY); / / after callback onDraw method canvas will path
Break;
Case MotionEvent.ACTION_MOVE:
mPath.lineTo(x, y);//After calling the onDraw method, the canvas draws a line to (x, y).
mLastX = x; / / update x coordinates
mLastY = y; / / update y coordinates
Break;
Default:break;
}
Invalidate();//Refresh View, callback onDraw method
Log.d(TAG, "onTouchEvent: invalidate");
Return true;
}
}