├── .gitattributes ├── .gitignore ├── README.md ├── WScratchViewLibrary ├── AndroidManifest.xml ├── libs │ └── android-support-v4.jar ├── proguard-project.txt ├── project.properties ├── res │ ├── drawable-hdpi │ │ └── ic_launcher.png │ ├── drawable-mdpi │ │ └── ic_launcher.png │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ └── values │ │ ├── attrs.xml │ │ ├── strings.xml │ │ └── styles.xml └── src │ └── com │ └── winsontan520 │ ├── IWScratchView.java │ └── WScratchView.java ├── github_screenshot.png └── testWScratchView ├── AndroidManifest.xml ├── ic_launcher-web.png ├── libs └── android-support-v4.jar ├── proguard-project.txt ├── project.properties ├── res ├── drawable-hdpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── drawable-xhdpi │ ├── ic_launcher.png │ └── treasure.jpg ├── drawable-xxhdpi │ └── ic_launcher.png ├── drawable │ └── test.JPG ├── layout │ ├── default_codes.xml │ ├── default_xml.xml │ ├── image_overlay_bitmap.xml │ ├── image_overlay_drawable.xml │ └── image_overlay_xml.xml ├── menu │ └── activity_main.xml ├── values-v11 │ └── styles.xml ├── values-v14 │ └── styles.xml └── values │ ├── strings.xml │ └── styles.xml └── src └── com └── winsontan520 └── testwscratchview ├── DefaultCodes.java ├── DefaultXML.java ├── Demos.java ├── ImageOverlayBitmap.java ├── ImageOverlayDrawable.java └── ImageOverlayXML.java /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | WScratchViewJar/gen/ 2 | WScratchViewLibrary/gen/ 3 | testWScratchView/gen/ 4 | 5 | 6 | ################# 7 | ## Eclipse 8 | ################# 9 | 10 | *.pydevproject 11 | .project 12 | .metadata 13 | bin/ 14 | tmp/ 15 | gen/ 16 | *.tmp 17 | *.bak 18 | *.swp 19 | *~.nib 20 | local.properties 21 | .classpath 22 | .settings/ 23 | .loadpath 24 | 25 | # External tool builders 26 | .externalToolBuilders/ 27 | 28 | # Locally stored "Eclipse launch configurations" 29 | *.launch 30 | 31 | # CDT-specific 32 | .cproject 33 | 34 | # PDT-specific 35 | .buildpath 36 | 37 | 38 | ################# 39 | ## Visual Studio 40 | ################# 41 | 42 | ## Ignore Visual Studio temporary files, build results, and 43 | ## files generated by popular Visual Studio add-ons. 44 | 45 | # User-specific files 46 | *.suo 47 | *.user 48 | *.sln.docstates 49 | 50 | # Build results 51 | [Dd]ebug/ 52 | [Rr]elease/ 53 | *_i.c 54 | *_p.c 55 | *.ilk 56 | *.meta 57 | *.obj 58 | *.pch 59 | *.pdb 60 | *.pgc 61 | *.pgd 62 | *.rsp 63 | *.sbr 64 | *.tlb 65 | *.tli 66 | *.tlh 67 | *.tmp 68 | *.vspscc 69 | .builds 70 | *.dotCover 71 | 72 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 73 | #packages/ 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opensdf 80 | *.sdf 81 | 82 | # Visual Studio profiler 83 | *.psess 84 | *.vsp 85 | 86 | # ReSharper is a .NET coding add-in 87 | _ReSharper* 88 | 89 | # Installshield output folder 90 | [Ee]xpress 91 | 92 | # DocProject is a documentation generator add-in 93 | DocProject/buildhelp/ 94 | DocProject/Help/*.HxT 95 | DocProject/Help/*.HxC 96 | DocProject/Help/*.hhc 97 | DocProject/Help/*.hhk 98 | DocProject/Help/*.hhp 99 | DocProject/Help/Html2 100 | DocProject/Help/html 101 | 102 | # Click-Once directory 103 | publish 104 | 105 | # Others 106 | [Bb]in 107 | [Oo]bj 108 | sql 109 | TestResults 110 | *.Cache 111 | ClientBin 112 | stylecop.* 113 | ~$* 114 | *.dbmdl 115 | Generated_Code #added for RIA/Silverlight projects 116 | 117 | # Backup & report files from converting an old project file to a newer 118 | # Visual Studio version. Backup files are not needed, because we have git ;-) 119 | _UpgradeReport_Files/ 120 | Backup*/ 121 | UpgradeLog*.XML 122 | 123 | 124 | 125 | ############ 126 | ## Windows 127 | ############ 128 | 129 | # Windows image file caches 130 | Thumbs.db 131 | 132 | # Folder config file 133 | Desktop.ini 134 | 135 | 136 | ############# 137 | ## Python 138 | ############# 139 | 140 | *.py[co] 141 | 142 | # Packages 143 | *.egg 144 | *.egg-info 145 | dist 146 | build 147 | eggs 148 | parts 149 | bin 150 | var 151 | sdist 152 | develop-eggs 153 | .installed.cfg 154 | 155 | # Installer logs 156 | pip-log.txt 157 | 158 | # Unit test / coverage reports 159 | .coverage 160 | .tox 161 | 162 | #Translations 163 | *.mo 164 | 165 | #Mr Developer 166 | .mr.developer.cfg 167 | 168 | # Mac crap 169 | .DS_Store 170 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Android-WScratchView [Deprecated] 2 | ==================== 3 | ## PLEASE NOTE, THIS PROJECT IS NO LONGER BEING MAINTAINED, YOU ARE WELCOME TO COPY AND IMPROVE AS YOUR OWN PROJECT. PLEASE INFORM ME THE IMPROVED VERSION SO I CAN LINK IT FOR OTHER USERS 4 | #### NOTE: This is NOT the best method but just a quick hack, the overlay will always on top of all layout. Improvement is needed for drawing one time on surface instead drawing multiple times. 5 | 6 | ## Features 7 | This is a simple library that provide a quick implementation by writing code in xml layout to create a view which can be scratched to reveal items behind it like Scratchcard! 8 | 9 | ## Progress Note 10 | Please use only project library for latest build 11 | 12 | ## Changelog 13 | - v1.0 First version - Color Overlay 14 | - v1.1 Add image overlay (Experimental) and getPercentage with callback (thanks to davefong) 15 | - v1.2 Add Click Listener and Automatically Scratch All Features (by gilbert1991) 16 | 17 | ## Todo 18 | - update Image Overlay (done 23 June 2014) 19 | - update getPercentage (done 23 June 2014) 20 | - update project structures 21 | - update google play sample 22 | - update tutorial 23 | 24 | ## Screenshots 25 | ![Screenshot](https://github.com/winsontan520/Android-WScratchView/raw/master/github_screenshot.png) 26 | 27 | ## Demo 28 | [![Get it on Google Play](http://www.android.com/images/brand/get_it_on_play_logo_small.png)](https://play.google.com/store/apps/details?id=com.winsontan520.testwscratchview) 29 | 30 | ## Usage 31 | ## Option 1: With library project 32 | 1. Git clone the project git://github.com/winsontan520/Android-WScratchView.git 33 | 2. For Eclipse, Import > Existing Android Code Into Workspace > Browse folder WScratchViewLibrary > Finish 34 | 3. Build the imported library project 35 | 4. Include the library in your project by right click your project > Android > In library tab click Add and choose the imported library 36 | For testing, you may use sample project by import the folder testWScratchView and add the library 37 | If you never include library project, I would recommend you to use option 2. 38 | 5. To call the view, in your layout xml, 39 | 40 | 50 | 51 | 52 | 6. You can customize the overlay color, size and other attributes by changing the value. The attributes are self explanatory. 53 | 54 | ## Contributions 55 | 56 | * [daveyfong](https://github.com/daveyfong) 57 | * [gilbert1991](https://github.com/gilbert1991) 58 | 59 | ## License 60 | Copyright 2013 Winson Tan 61 | 62 | Licensed under the Apache License, Version 2.0 (the "License"); 63 | you may not use this file except in compliance with the License. 64 | You may obtain a copy of the License at 65 | 66 | http://www.apache.org/licenses/LICENSE-2.0 67 | 68 | Unless required by applicable law or agreed to in writing, software 69 | distributed under the License is distributed on an "AS IS" BASIS, 70 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 71 | See the License for the specific language governing permissions and 72 | limitations under the License. 73 | -------------------------------------------------------------------------------- /WScratchViewLibrary/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /WScratchViewLibrary/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WScratchView/320e6c45d9b52d2735d08b4fd6ecfd3a98f4041f/WScratchViewLibrary/libs/android-support-v4.jar -------------------------------------------------------------------------------- /WScratchViewLibrary/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /WScratchViewLibrary/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=Google Inc.:Google APIs:19 15 | android.library=true 16 | -------------------------------------------------------------------------------- /WScratchViewLibrary/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WScratchView/320e6c45d9b52d2735d08b4fd6ecfd3a98f4041f/WScratchViewLibrary/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /WScratchViewLibrary/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WScratchView/320e6c45d9b52d2735d08b4fd6ecfd3a98f4041f/WScratchViewLibrary/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /WScratchViewLibrary/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WScratchView/320e6c45d9b52d2735d08b4fd6ecfd3a98f4041f/WScratchViewLibrary/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /WScratchViewLibrary/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /WScratchViewLibrary/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | WScratchView 4 | 5 | -------------------------------------------------------------------------------- /WScratchViewLibrary/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 14 | 15 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /WScratchViewLibrary/src/com/winsontan520/IWScratchView.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2013 Winson Tan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.winsontan520; 17 | 18 | import com.winsontan520.WScratchView.OnScratchCallback; 19 | 20 | import android.graphics.Bitmap; 21 | import android.graphics.drawable.Drawable; 22 | 23 | public interface IWScratchView { 24 | 25 | /** 26 | * Whether the view receive user on touch motion 27 | * 28 | * @return true if scratchable 29 | */ 30 | public boolean isScratchable(); 31 | 32 | /** 33 | * If true, set the view allow receive on touch to reveal the view 34 | * By default, scratchable is true 35 | * 36 | * @param flag - flag for enable/disable scratch 37 | */ 38 | public void setScratchable(boolean flag); 39 | 40 | /** 41 | * Set the color of overlay 42 | * 43 | * @param ResId - resources identifier for color in INT type 44 | */ 45 | public void setOverlayColor(int ResId); 46 | 47 | /** 48 | * Set the radius size of the circle to be revealed 49 | * 50 | * @param size - radius size of circle in pixel unit 51 | */ 52 | public void setRevealSize(int size); 53 | 54 | /** 55 | * Set turn on/off effect of anti alias of circle revealed 56 | * By default, anti alias is turn off 57 | * 58 | * @param flag - set true to turn on anti alias 59 | */ 60 | public void setAntiAlias(boolean flag); 61 | 62 | /** 63 | * Reset the scratch view 64 | * 65 | */ 66 | public void resetView(); 67 | 68 | /** 69 | * Set drawable for scratch view 70 | * 71 | * @param drawable - Set drawable for scratch view 72 | */ 73 | public void setScratchDrawable(Drawable drawable); 74 | 75 | /** 76 | * Set bitmap for scratch view 77 | * 78 | * @param bitmap - Set bitmap for scratch view 79 | */ 80 | public void setScratchBitmap(Bitmap b); 81 | 82 | /** 83 | * Get scratched ratio (contribution from daveyfong) 84 | * 85 | * @return float - return Scratched ratio 86 | */ 87 | public float getScratchedRatio(); 88 | 89 | /** 90 | * Get scratched ratio (contribution from daveyfong) 91 | * 92 | * @param int - Scratch speed 93 | * @return float - return Scratched ratio 94 | */ 95 | public float getScratchedRatio(int speed); 96 | 97 | public void setOnScratchCallback(OnScratchCallback callback); 98 | 99 | public void setScratchAll(boolean scratchAll); 100 | 101 | public void setBackgroundClickable(boolean clickable); 102 | } -------------------------------------------------------------------------------- /WScratchViewLibrary/src/com/winsontan520/WScratchView.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2013-present Winson Tan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.winsontan520; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | import android.content.Context; 22 | import android.content.res.TypedArray; 23 | import android.graphics.Bitmap; 24 | import android.graphics.Canvas; 25 | import android.graphics.Color; 26 | import android.graphics.Matrix; 27 | import android.graphics.Paint; 28 | import android.graphics.Path; 29 | import android.graphics.PixelFormat; 30 | import android.graphics.PorterDuff.Mode; 31 | import android.graphics.PorterDuffXfermode; 32 | import android.graphics.drawable.BitmapDrawable; 33 | import android.graphics.drawable.Drawable; 34 | import android.util.AttributeSet; 35 | import android.view.MotionEvent; 36 | import android.view.SurfaceHolder; 37 | import android.view.SurfaceView; 38 | 39 | /** 40 | * This view start with full gray color bitmap and onTouch to make it 41 | * transparent 42 | * 43 | * @author winsontan520 44 | */ 45 | public class WScratchView extends SurfaceView implements IWScratchView, SurfaceHolder.Callback { 46 | private static final String TAG = "WScratchView"; 47 | 48 | // default value constants 49 | private final int DEFAULT_COLOR = 0xff444444; // default color is dark gray 50 | private final int DEFAULT_REVEAL_SIZE = 30; 51 | 52 | public static final int DEFAULT_SCRATCH_TEST_SPEED = 4; 53 | 54 | private Context mContext; 55 | private WScratchViewThread mThread; 56 | List mPathList = new ArrayList(); 57 | private int mOverlayColor; 58 | private Paint mOverlayPaint; 59 | private int mRevealSize; 60 | private boolean mIsScratchable = true; 61 | private boolean mIsAntiAlias = false; 62 | private Path path; 63 | private float startX = 0; 64 | private float startY = 0; 65 | private boolean mScratchStart = false; 66 | private Bitmap mScratchBitmap; 67 | private Drawable mScratchDrawable = null; 68 | private Paint mBitmapPaint; 69 | private Matrix mMatrix; 70 | private Bitmap mScratchedTestBitmap; 71 | private Canvas mScratchedTestCanvas; 72 | private OnScratchCallback mOnScratchCallback; 73 | 74 | //Enable scratch all area if mClearCanvas is true 75 | private boolean mClearCanvas = false; 76 | //Enable click on WScratchView if mIsClickable is true 77 | private boolean mIsClickable = false; 78 | 79 | public WScratchView(Context ctx, AttributeSet attrs) { 80 | super(ctx, attrs); 81 | init(ctx, attrs); 82 | } 83 | 84 | public WScratchView(Context context) { 85 | super(context); 86 | init(context, null); 87 | } 88 | 89 | private void init(Context context, AttributeSet attrs) { 90 | mContext = context; 91 | 92 | // default value 93 | mOverlayColor = DEFAULT_COLOR; 94 | mRevealSize = DEFAULT_REVEAL_SIZE; 95 | 96 | TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.WScratchView, 0, 0); 97 | 98 | final int indexCount = ta.getIndexCount(); 99 | for (int i = 0; i < indexCount; i++) { 100 | int attr = ta.getIndex(i); 101 | switch (attr) { 102 | case R.styleable.WScratchView_overlayColor: 103 | mOverlayColor = ta.getColor(attr, DEFAULT_COLOR); 104 | break; 105 | case R.styleable.WScratchView_revealSize: 106 | mRevealSize = ta.getDimensionPixelSize(attr, DEFAULT_REVEAL_SIZE); 107 | break; 108 | case R.styleable.WScratchView_antiAlias: 109 | mIsAntiAlias = ta.getBoolean(attr, false); 110 | break; 111 | case R.styleable.WScratchView_scratchable: 112 | mIsScratchable = ta.getBoolean(attr, true); 113 | break; 114 | case R.styleable.WScratchView_scratchDrawable: 115 | mScratchDrawable = ta.getDrawable(R.styleable.WScratchView_scratchDrawable); 116 | break; 117 | } 118 | } 119 | 120 | setZOrderOnTop(true); 121 | SurfaceHolder holder = getHolder(); 122 | holder.addCallback(this); 123 | holder.setFormat(PixelFormat.TRANSPARENT); 124 | 125 | mOverlayPaint = new Paint(); 126 | mOverlayPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR)); 127 | mOverlayPaint.setStyle(Paint.Style.STROKE); 128 | mOverlayPaint.setStrokeCap(Paint.Cap.ROUND); 129 | mOverlayPaint.setStrokeJoin(Paint.Join.ROUND); 130 | 131 | // convert drawable to bitmap if drawable already set in xml 132 | if (mScratchDrawable != null) { 133 | mScratchBitmap = ((BitmapDrawable) mScratchDrawable).getBitmap(); 134 | } 135 | 136 | mBitmapPaint = new Paint(); 137 | mBitmapPaint.setAntiAlias(true); 138 | mBitmapPaint.setFilterBitmap(true); 139 | mBitmapPaint.setDither(true); 140 | } 141 | 142 | @Override 143 | public void onDraw(Canvas canvas) { 144 | super.onDraw(canvas); 145 | 146 | //Clear all area if mClearCanvas is true 147 | if(mClearCanvas){ 148 | canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR); 149 | return; 150 | } 151 | 152 | if (mScratchBitmap != null) { 153 | if (mMatrix == null) { 154 | float scaleWidth = (float) canvas.getWidth() / mScratchBitmap.getWidth(); 155 | float scaleHeight = (float) canvas.getHeight() / mScratchBitmap.getHeight(); 156 | mMatrix = new Matrix(); 157 | mMatrix.postScale(scaleWidth, scaleHeight); 158 | } 159 | canvas.drawBitmap(mScratchBitmap, mMatrix, mBitmapPaint); 160 | } else { 161 | canvas.drawColor(mOverlayColor); 162 | } 163 | 164 | for (Path path : mPathList) { 165 | mOverlayPaint.setAntiAlias(mIsAntiAlias); 166 | mOverlayPaint.setStrokeWidth(mRevealSize); 167 | 168 | canvas.drawPath(path, mOverlayPaint); 169 | } 170 | 171 | 172 | } 173 | 174 | private void updateScratchedPercentage() { 175 | if(mOnScratchCallback == null) return; 176 | mOnScratchCallback.onScratch(getScratchedRatio()); 177 | } 178 | 179 | @Override 180 | public boolean onTouchEvent(MotionEvent me) { 181 | synchronized (mThread.getSurfaceHolder()) { 182 | if (!mIsScratchable) { 183 | return true; 184 | } 185 | 186 | switch (me.getAction()) { 187 | case MotionEvent.ACTION_DOWN: 188 | path = new Path(); 189 | path.moveTo(me.getX(), me.getY()); 190 | startX = me.getX(); 191 | startY = me.getY(); 192 | mPathList.add(path); 193 | break; 194 | case MotionEvent.ACTION_MOVE: 195 | if (mScratchStart) { 196 | path.lineTo(me.getX(), me.getY()); 197 | } else { 198 | if (isScratch(startX, me.getX(), startY, me.getY())) { 199 | mScratchStart = true; 200 | path.lineTo(me.getX(), me.getY()); 201 | } 202 | } 203 | updateScratchedPercentage(); 204 | break; 205 | case MotionEvent.ACTION_UP: 206 | //Set call back if user's finger detach 207 | if(mOnScratchCallback != null){ 208 | mOnScratchCallback.onDetach(true); 209 | } 210 | //perform Click action if the motion is not move 211 | //and the WScratchView is clickable 212 | if(!mScratchStart && mIsClickable){ 213 | post(new Runnable() { 214 | @Override 215 | public void run() { 216 | performClick(); 217 | } 218 | }); 219 | } 220 | mScratchStart = false; 221 | break; 222 | } 223 | return true; 224 | } 225 | } 226 | 227 | private boolean isScratch(float oldX, float x, float oldY, float y) { 228 | float distance = (float) Math.sqrt(Math.pow(oldX - x, 2) + Math.pow(oldY - y, 2)); 229 | if (distance > mRevealSize * 2) { 230 | return true; 231 | } else { 232 | return false; 233 | } 234 | } 235 | 236 | @Override 237 | public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { 238 | // do nothing 239 | } 240 | 241 | @Override 242 | public void surfaceCreated(SurfaceHolder arg0) { 243 | mThread = new WScratchViewThread(getHolder(), this); 244 | mThread.setRunning(true); 245 | mThread.start(); 246 | 247 | mScratchedTestBitmap = Bitmap.createBitmap(arg0.getSurfaceFrame().width(), arg0.getSurfaceFrame().height(), Bitmap.Config.ARGB_8888); 248 | mScratchedTestCanvas = new Canvas(mScratchedTestBitmap); 249 | } 250 | 251 | @Override 252 | public void surfaceDestroyed(SurfaceHolder arg0) { 253 | boolean retry = true; 254 | mThread.setRunning(false); 255 | while (retry) { 256 | try { 257 | mThread.join(); 258 | retry = false; 259 | } catch (InterruptedException e) { 260 | // do nothing but keep retry 261 | } 262 | } 263 | 264 | } 265 | 266 | class WScratchViewThread extends Thread { 267 | private SurfaceHolder mSurfaceHolder; 268 | private WScratchView mView; 269 | private boolean mRun = false; 270 | 271 | public WScratchViewThread(SurfaceHolder surfaceHolder, WScratchView view) { 272 | mSurfaceHolder = surfaceHolder; 273 | mView = view; 274 | } 275 | 276 | public void setRunning(boolean run) { 277 | mRun = run; 278 | } 279 | 280 | public SurfaceHolder getSurfaceHolder() { 281 | return mSurfaceHolder; 282 | } 283 | 284 | @Override 285 | public void run() { 286 | Canvas c; 287 | while (mRun) { 288 | c = null; 289 | try { 290 | c = mSurfaceHolder.lockCanvas(null); 291 | synchronized (mSurfaceHolder) { 292 | if (c != null) { 293 | mView.draw(c); 294 | } 295 | } 296 | } finally { 297 | if (c != null) { 298 | mSurfaceHolder.unlockCanvasAndPost(c); 299 | } 300 | } 301 | } 302 | } 303 | } 304 | 305 | @Override 306 | public void resetView() { 307 | synchronized (mThread.getSurfaceHolder()) { 308 | mPathList.clear(); 309 | } 310 | } 311 | 312 | @Override 313 | public boolean isScratchable() { 314 | return mIsScratchable; 315 | } 316 | 317 | @Override 318 | public void setScratchable(boolean flag) { 319 | mIsScratchable = flag; 320 | } 321 | 322 | @Override 323 | public void setOverlayColor(int ResId) { 324 | mOverlayColor = ResId; 325 | } 326 | 327 | @Override 328 | public void setRevealSize(int size) { 329 | mRevealSize = size; 330 | } 331 | 332 | @Override 333 | public void setAntiAlias(boolean flag) { 334 | mIsAntiAlias = flag; 335 | } 336 | 337 | @Override 338 | public void setScratchDrawable(Drawable d) { 339 | mScratchDrawable = d; 340 | if (mScratchDrawable != null) { 341 | mScratchBitmap = ((BitmapDrawable) mScratchDrawable).getBitmap(); 342 | } 343 | } 344 | 345 | @Override 346 | public void setScratchBitmap(Bitmap b) { 347 | mScratchBitmap = b; 348 | } 349 | 350 | @Override 351 | public float getScratchedRatio() { 352 | return getScratchedRatio(DEFAULT_SCRATCH_TEST_SPEED); 353 | } 354 | 355 | /** 356 | * thanks to https://github.com/daveyfong for providing this method 357 | */ 358 | @Override 359 | public float getScratchedRatio(int speed) { 360 | if (null == mScratchedTestBitmap) { 361 | return 0; 362 | } 363 | draw(mScratchedTestCanvas); 364 | 365 | final int width = mScratchedTestBitmap.getWidth(); 366 | final int height = mScratchedTestBitmap.getHeight(); 367 | 368 | int count = 0; 369 | for (int i = 0; i < width; i += speed) { 370 | for (int j = 0; j < height; j += speed) { 371 | if (0 == Color.alpha(mScratchedTestBitmap.getPixel(i, j))) { 372 | count++; 373 | } 374 | } 375 | } 376 | float completed = (float) count / ((width / speed) * (height / speed)) * 100; 377 | 378 | return completed; 379 | } 380 | 381 | @Override 382 | public void setOnScratchCallback(OnScratchCallback callback) { 383 | mOnScratchCallback = callback; 384 | } 385 | 386 | public static abstract class OnScratchCallback{ 387 | public abstract void onScratch(float percentage); 388 | //Call back funtion to monitor the status of finger 389 | public abstract void onDetach(boolean fingerDetach); 390 | } 391 | 392 | //Set the mClearCanvas 393 | @Override 394 | public void setScratchAll(boolean scratchAll){ 395 | mClearCanvas = scratchAll; 396 | } 397 | 398 | //Set the WScartchView clickable 399 | @Override 400 | public void setBackgroundClickable(boolean clickable){ 401 | mIsClickable = clickable; 402 | } 403 | } 404 | -------------------------------------------------------------------------------- /github_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WScratchView/320e6c45d9b52d2735d08b4fd6ecfd3a98f4041f/github_screenshot.png -------------------------------------------------------------------------------- /testWScratchView/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /testWScratchView/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WScratchView/320e6c45d9b52d2735d08b4fd6ecfd3a98f4041f/testWScratchView/ic_launcher-web.png -------------------------------------------------------------------------------- /testWScratchView/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WScratchView/320e6c45d9b52d2735d08b4fd6ecfd3a98f4041f/testWScratchView/libs/android-support-v4.jar -------------------------------------------------------------------------------- /testWScratchView/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /testWScratchView/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=Google Inc.:Google APIs:19 15 | android.library.reference.1=../WScratchViewLibrary 16 | -------------------------------------------------------------------------------- /testWScratchView/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WScratchView/320e6c45d9b52d2735d08b4fd6ecfd3a98f4041f/testWScratchView/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /testWScratchView/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WScratchView/320e6c45d9b52d2735d08b4fd6ecfd3a98f4041f/testWScratchView/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /testWScratchView/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WScratchView/320e6c45d9b52d2735d08b4fd6ecfd3a98f4041f/testWScratchView/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /testWScratchView/res/drawable-xhdpi/treasure.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WScratchView/320e6c45d9b52d2735d08b4fd6ecfd3a98f4041f/testWScratchView/res/drawable-xhdpi/treasure.jpg -------------------------------------------------------------------------------- /testWScratchView/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WScratchView/320e6c45d9b52d2735d08b4fd6ecfd3a98f4041f/testWScratchView/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /testWScratchView/res/drawable/test.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/winsontan520/Android-WScratchView/320e6c45d9b52d2735d08b4fd6ecfd3a98f4041f/testWScratchView/res/drawable/test.JPG -------------------------------------------------------------------------------- /testWScratchView/res/layout/default_codes.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 15 | 16 | 22 | 23 | 29 | 30 |