Is the scratch card Effect of Android custom controls really just a scratch card? android scratch card
Reprint please indicate the source: http://blog.csdn.net/lmj623565791/article/details/40162163, this article from: [Zhang Hongyang blog]
A long time ago, I had an html5 scratch card ~~ Last time I saw someone write Android scratch cards ~~ As a result, this blog is generated ~~ There are also many such examples. You can refer to Baidu for more information ~ However, we can use this example to discover the hidden knowledge in it ~
1. Xfermode and PorterDuff
If you still remember, I used to blog on How to perfectly achieve image rounded corners and circles, and briefly introduced the implementation principle of rounded corners.
First, let's take a look at the official example, which shows the effects of 16 modes:
Note: Dst is drawn first, and Src is then drawn.
Now, after reading this figure, I will ask you a few questions:
Question 1: How can I implement a circular image?
A: First draw our image, then draw a circle on it, and the final result is a circular image; and so on, how can we generate it? Please refer to the above SrcIn mode;
The Dst is drawn first, then DstIn is set, and Src is drawn. The final result is that the intersection of the two is the Dst part. Next we will bring our answer to it.
Draw an image first, then set DstIn, and then draw a circle. The final effect is to leave the intersection of the two and the part of the image; well, what is the intersection, the circle; what is the circular content, and the image; search for shards.
----
Wait. I have another idea: first draw a circle, then set SrcIn, and then draw our image. Also, we can generate a circular image. Let's take a look:
What SrcIn eventually retains is still the intersection, but it is displayed as the post-drawn image, that is, our image. You can search for the result.
Question 2: How can I implement a rounded image?
A: After reading the answer above, you have no idea. Change the circle to the rounded rectangle. What else do you want to ask? Yes, yes.
Well, we changed the circle in question 1 to a rounded corner and implemented our rounded corner image according to the same drawing process.
Question 3: Is this related to our scratch card?
A: It doesn't matter. You should first draw the scratch layer, then set DST_OUT, and then draw the lines touched by your hand. The user will touch the part of the scratch layer (intersection part) the display is the line touched by the user. If the line is transparent, it means that the scratch layer is erased by us ~
This is not a prize. What about the prize?
The prize is nothing more than text or images. Draw it in advance, draw a scratch layer on it, set DST_OUT, and draw the user touch; after this disappears, you will be able to see the award ~~~ By the way, there is also an app called to take off the sister's clothes. First draw the sister, then draw the clothes, and then wipe the clothes ~~ This is not like the image of the prize. I didn't say anything about it.
Search, after the above three questions, we should understand what the principle of rounded corners, circles, and scratch cards is so simple ,,,
2. Implementation of simple canvas
Our scratch cards need to grasp the drawing. Of course, you do not need to have an artistic talent here. You can just use graffiti ~~
The following is a simple canvas. You can draw a line on it. Of course, you can sign it. Our View is called GuaGuaKa:
1. Initial GuaGuaKa
Package com. zhy. view; import android. content. context; import android. graphics. bitmap; import android. graphics. bitmap. config; import android. graphics. canvas; import android. graphics. color; import android. graphics. paint; import android. graphics. path; import android. util. attributeSet; import android. view. motionEvent; import android. view. view; public class GuaGuaKa extends View {/*** painting of a line, that is, drawing Path */private Paint mOutterPaint = new Paint () by your fingers (); /*** record the user-drawn Path */private Path mPath = new Path ();/*** Canvas created in memory */private Canvas mCanvas; /*** Add the mCanvas image to it */private Bitmap mBitmap; private int mLastX; private int mLastY; public GuaGuaKa (Context context) {this (context, null );} public GuaGuaKa (Context context, AttributeSet attrs) {this (context, attrs, 0);} public GuaGuaKa (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle); init () ;}private void init () {mPath = new Path () ;}@ Overrideprotected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {super. onMeasure (widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth (); int height = getMeasuredHeight (); // initialize bitmapmBitmap = Bitmap. createBitmap (width, height, Config. ARGB_8888); mCanvas = new Canvas (mBitmap); // set the paint brush mOutterPaint. setColor (Color. RED); mOutterPaint. setAntiAlias (true); mOutterPaint. setDither (true); mOutterPaint. setStyle (Paint. style. STROKE); mOutterPaint. setStrokeJoin (Paint. join. ROUND); // rounded corner mOutterPaint. setStrokeCap (Paint. cap. ROUND); // rounded corner // set the paint width mOutterPaint. setStrokeWidth (20) ;}@ Overrideprotected void onDraw (Canvas canvas) {drawPath (); canvas. drawBitmap (mBitmap, 0, 0, null);}/*** draw line */private void drawPath () {mCanvas. drawPath (mPath, mOutterPaint);} @ Overridepublic boolean onTouchEvent (MotionEvent event) {int action = event. getAction (); int x = (int) event. getX (); int y = (int) event. getY (); switch (action) {case MotionEvent. ACTION_DOWN: mLastX = x; mLastY = y; mPath. moveTo (mLastX, mLastY); break; case MotionEvent. ACTION_MOVE: int dx = Math. abs (x-mLastX); int dy = Math. abs (y-mLastY); if (dx> 3 | dy> 3) mPath. lineTo (x, y); mLastX = x; mLastY = y; break;} invalidate (); return true ;}}
The amount of code is relatively small. We create a mCanvas in the memory, create an mBitmap, and then use our preset mOuterPaint to draw an mPath on our mBitmap through mCanvas;
What is the data in mPath? It is the constant moveTo in the onTouchEvent, and lineTo is good ~~ The code is quite casual.
Finally, pay attention to drawing the mBitmap on the memory, and then display our mBitmap through the view canvas. Why.
Well, now you can scatter it on our canvas:
The layout file and running effect are as follows:
2. layout files and running results
Layout file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <com.zhy.view.GuaGuaKa android:layout_width="match_parent" android:layout_height="match_parent" /></RelativeLayout>
Running effect:
I don't have any font. I will become a calligrapher when I can't write the program later ~
Now, after our simple canvas is complete, we start to consider the subject and step by step approach our Scratch board. Now we are ready to do this. First, we will draw an image behind our back, then draw a covering layer, and the painting process is to erase the covering layer.
3. The first implementation of Erasure
In view of the opinions of many friends, I decided to use a Landscape Map for this image to stay away from xxx. Thanks to the image provided by seven ~
1. Draw a covering layer
In fact, the covering layer is a color:
@ Overrideprotected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {super. onMeasure (widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth (); int height = getMeasuredHeight (); // initialize bitmapmBitmap = Bitmap. createBitmap (width, height, Config. ARGB_8888); mCanvas = new Canvas (mBitmap); setUpOutPaint (); // you can change this to mCanvas. drawColor (Color. parseColor ("# c0c0c0 "));}
The last line of the above Code is added, and our paint settings are extracted ~
2. drawPath
The principle at the beginning of this article is finally used. We need to set a mode when drawing the Path. Here is DST_OUT. I am a little excited ~
private void drawPath(){mOutterPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));mCanvas.drawPath(mPath, mOutterPaint);}
3. onDraw
Make some modifications in onDraw.
@Overrideprotected void onDraw(Canvas canvas){canvas.drawBitmap(mBackBitmap, 0, 0, null);drawPath();canvas.drawBitmap(mBitmap, 0, 0, null);}
Now we have added several lines of code to complete the transformation from simple canvas to scratch;
See the following results:
Is there any feeling of opening the cloud ~~
At this point, our scratch card principle and preliminary implementation have ended ~~ It's quite easy ~ The next step is the subsequent improvement work.
4. Complete scratch cards
We are going to change the award to a font and draw the font in the middle of the screen;
You just need to change the above image to the font, but there is an additional Font paint brush setting:
Changed code:
Private Paint mBackPint = new Paint (); private Rect mTextBound = new Rect (); private String mText = ", 000 "; /*** specifies the paint brush used to initialize canvas painting */private void setUpBackPaint () {mBackPint. setStyle (Style. FILL); mBackPint. setTextScaleX (2f); mBackPint. setColor (Color. DKGRAY); mBackPint. setTextSize (22); mBackPint. getTextBounds (mText, 0, mText. length (), mTextBound);} @ Overrideprotected void onDraw (Canvas canvas) {// canvas. drawBitmap (mBackBitmap, 0, 0, null); // draw the award canvas. drawText (mText, getWidth ()/2-mTextBound. width ()/2, getHeight ()/2 + mTextBound. height ()/2, mBackPint); drawPath (); canvas. drawBitmap (mBitmap, 0, 0, null );}
Next let's take a look at how much money I spent:
Well, it has been fully implemented. You can modify the principles mentioned in the examples based on your needs. I believe the principles have been clearly explained. By the way, I almost forgot, scratch cards generally have a function. When you are down, the coating will be automatically cleared. Next we will try to add this function.
5. Count the percentage of existing scratch Areas
When ACTION_UP, we can perform computation. First, we will instill in everyone the computing principle. If you read it carefully, you should know that all our operations are basically in mBitmap, now we get the data of all pixels on the mBItmap, and calculate the cleared area (the cleared pixel is 0). Finally, we calculate the Division element with the total number of pixels of our image, we can get the percentage we cleared;
However, computing may be a time-consuming operation. The specific speed is related to the image size. Therefore, we decided to use Asynchronous calculation:
/*** Calculate and erase regional tasks */private Runnable mRunnable = new Runnable () {private int [] mPixels; @ Overridepublic void run () {int w = getWidth (); int h = getHeight (); float wipeArea = 0; float totalArea = w * h; Bitmap bitmap = mBitmap; mPixels = new int [w * h]; /*** get all the pixel information */bitmap. getPixels (mPixels, 0, w, 0, 0, w, h);/*** traverse the erased area of statistics */for (int I = 0; I <w; I ++) {for (int j = 0; j
With this task, we can call it when ACTION_UP:
case MotionEvent.ACTION_UP:new Thread(mRunnable).start();break;
Note that after the task is completed, an isComplete is set to true. When it is set to true, the scratch area is displayed directly.
@Overrideprotected void onDraw(Canvas canvas){drawBackText(canvas);if (!isComplete){drawPath();canvas.drawBitmap(mBitmap, 0, 0, null);}}
The calculation in this lottery area is over.
Before the demonstration, I made some simple beautification. You can view the source code at that time.
At this point, the scratch card is finished. If you want to improve it, you can set many constants in it as variables, add external set methods, or extract them into custom attributes, you can define all layout files ~~~
One thing to note is that in our Scratch case, if we set the layout file to wrap_content in width and height, the screen will be full, mainly because I don't think wrap_content is necessary for the scratch view; if you want to support wrp_content, see Android custom View (1 ).
Download source code
Bytes ---------------------------------------------------------------------------------------------------------
I have created a QQ Group for your convenience. Group Number:55032675
Bytes ----------------------------------------------------------------------------------------------------------
Some of the bloggers have already been online. If you do not like boring text, stamp it (for initial record, we look forward to your support ):
1. High imitation 5.2.1 main interface and message reminder
2. High imitation QQ5.0 slide
Some people have encountered js compatibility issues during scratch on the development platform ?? Some mobile phones cannot be scraped. Help
In fact, this problem is caused by a lot of software issues with the mobile phone compatibility of users, which is related to mobile phone manufacturers and software vendors. It is impossible to do anything that cannot be solved. When users cannot do anything, they can only comfort them or ask them to log on with other mobile devices. Hope to adopt
What are the functions of scratch cards?
First, the dynamic password is the password of the electronic password card. In addition, our system will automatically identify whether the password of the electronic password you entered is correct. If you are prompted that your password is incorrect, note that do not copy the password, do not contain spaces, and try again in the English half-width input method. The electronic card is printed with several strings in the form of a matrix. When you use the electronic bank for external transfers, B2C shopping, payment, and other payment transactions, the electronic bank system will randomly give a set of sequence card coordinates, you can find the password combination from the card according to the coordinates and enter the electronic banking system. Only the customer with the correct password combination can complete the transaction. The password combination is valid once and expires after the transaction ends. For details about how to use the electronic registration card, visit www.icbc.com.cn/...ma.htm. Please log on to your personal online bank, choose "Customer Service"> "Customer Information Management"> "query and modify customer information" to check whether the serial number of the traffic card is consistent with that of the physical traffic card. If the serial number is different, please apply for a new card at your bank outlet with a valid certificate and online bank registration card or registered account. If you apply for a new card, the old card will be voided. If the information is consistent, check the following content: 1. When you use an electronic password card for payment, the expiration time of the password card is limited to 85 seconds. Please enter the corresponding coordinates on the payment page as soon as possible. 2. During B2C payment transactions, Please carefully check the password of the password card. The bank will temporarily freeze the client's online banking qualification for the current day, the freeze is automatically released the next day. The bank will freeze the customer's online banking transaction qualifications when the wrong dynamic password is lost for 10 consecutive times, you need to bring your valid ID card, any online bank registration card or registered account, and the password card to any outlet to change the password card. For details about the outlets that handle the business, please contact us at 95588. 3. For the customer of the logging card, the parameter control of "limit on the number of empty passwords on the current day" and "limit on the number of historical empty passwords on the dynamic password card" is added. The specific parameter values are 5 times and 10 times respectively. When a challenge coordinate value is obtained and the correct value is entered, the number of retrieved challenges is set to 0. If the coordinate value is not entered, the number of retrieved challenges is increased by 1; when an incorrect coordinate value is entered, the number of retrieved challenges remains unchanged. When the value of the number of retrieved coordinates reaches the "dynamic password card when the number of blank clicks limit", the logging card will be temporarily locked and cannot be traded on the current day. If you still need to make a logging card transaction on the current day, you need to carry a valid ID card, an electronic password card, or any of your online banking registration cards or registered accounts to the "Certificate proxy" outlet to clear Blank Password cards. When the number of times of obtaining the coordinates of the challenge reaches the "limit on the number of empty refresh attempts in the history of the dynamic cryptographic card", the logging card will be permanently locked and you will not be able to trade the logging card any more, you need to carry a valid certificate, an electronic password card, or any of your online banking registration cards or registered accounts to the "Certificate proxy" outlet to clear Blank Password cards. For outlet information, you can contact the local 95588