├── .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 | 
26 |
27 | ## Demo
28 | [](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 |
39 |
40 |
--------------------------------------------------------------------------------
/testWScratchView/res/layout/default_xml.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
15 |
16 |
22 |
23 |
33 |
34 |
43 |
44 |
--------------------------------------------------------------------------------
/testWScratchView/res/layout/image_overlay_bitmap.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
15 |
16 |
22 |
23 |
29 |
30 |
39 |
40 |
--------------------------------------------------------------------------------
/testWScratchView/res/layout/image_overlay_drawable.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
15 |
16 |
22 |
23 |
29 |
30 |
39 |
40 |
--------------------------------------------------------------------------------
/testWScratchView/res/layout/image_overlay_xml.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
15 |
16 |
22 |
23 |
33 |
34 |
43 |
44 |
--------------------------------------------------------------------------------
/testWScratchView/res/menu/activity_main.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/testWScratchView/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/testWScratchView/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/testWScratchView/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WScratchView Sample
5 | Hello world!
6 | Settings
7 |
8 |
--------------------------------------------------------------------------------
/testWScratchView/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
--------------------------------------------------------------------------------
/testWScratchView/src/com/winsontan520/testwscratchview/DefaultCodes.java:
--------------------------------------------------------------------------------
1 | package com.winsontan520.testwscratchview;
2 |
3 | import android.app.Activity;
4 | import android.graphics.Color;
5 | import android.os.Bundle;
6 | import android.view.Menu;
7 | import android.view.View;
8 | import android.view.View.OnClickListener;
9 | import android.widget.TextView;
10 | import android.widget.Toast;
11 |
12 | import com.winsontan520.testwscratchview.R;
13 | import com.winsontan520.WScratchView;
14 |
15 | public class DefaultCodes extends Activity {
16 | private WScratchView scratchView;
17 | private TextView percentageView;
18 | private float mPercentage;
19 |
20 | @Override
21 | protected void onCreate(Bundle savedInstanceState) {
22 | super.onCreate(savedInstanceState);
23 | setContentView(R.layout.default_codes);
24 |
25 | percentageView = (TextView) findViewById(R.id.percentage);
26 | scratchView = (WScratchView) findViewById(R.id.scratch_view);
27 |
28 | // customize attribute programmatically
29 | scratchView.setScratchable(true);
30 | scratchView.setRevealSize(50);
31 | scratchView.setAntiAlias(true);
32 | scratchView.setOverlayColor(Color.RED);
33 | scratchView.setBackgroundClickable(true);
34 |
35 | // add callback for update scratch percentage
36 | scratchView.setOnScratchCallback(new WScratchView.OnScratchCallback() {
37 |
38 | @Override
39 | public void onScratch(float percentage) {
40 | updatePercentage(percentage);
41 | }
42 |
43 | @Override
44 | public void onDetach(boolean fingerDetach) {
45 | if(mPercentage > 50){
46 | scratchView.setScratchAll(true);
47 | updatePercentage(100);
48 | }
49 | }
50 | });
51 |
52 | scratchView.setOnClickListener(new OnClickListener(){
53 |
54 | @Override
55 | public void onClick(View v) {
56 | Toast.makeText(DefaultCodes.this, "Clicked", Toast.LENGTH_SHORT).show();
57 | }
58 |
59 | });
60 |
61 | updatePercentage(0f);
62 | }
63 |
64 | protected void updatePercentage(float percentage) {
65 | mPercentage = percentage;
66 | String percentage2decimal = String.format("%.2f", percentage) + " %";
67 | percentageView.setText(percentage2decimal);
68 | }
69 |
70 | @Override
71 | public boolean onCreateOptionsMenu(Menu menu) {
72 | // Inflate the menu; this adds items to the action bar if it is present.
73 | getMenuInflater().inflate(R.menu.activity_main, menu);
74 | return true;
75 | }
76 |
77 | public void onClickHandler(View view) {
78 | switch (view.getId()) {
79 | case R.id.reset_button:
80 | scratchView.resetView();
81 | scratchView.setScratchAll(false); // todo: should include to resetView?
82 | updatePercentage(0f);
83 | break;
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/testWScratchView/src/com/winsontan520/testwscratchview/DefaultXML.java:
--------------------------------------------------------------------------------
1 | package com.winsontan520.testwscratchview;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.view.Menu;
6 | import android.view.View;
7 | import android.widget.TextView;
8 |
9 | import com.winsontan520.WScratchView;
10 |
11 | public class DefaultXML extends Activity {
12 | private WScratchView scratchView;
13 | private TextView percentageView;
14 | private float mPercentage;
15 |
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | setContentView(R.layout.default_xml);
20 |
21 | percentageView = (TextView) findViewById(R.id.percentage);
22 |
23 | scratchView = (WScratchView) findViewById(R.id.scratch_view);
24 |
25 | // add callback for update scratch percentage
26 | scratchView.setOnScratchCallback(new WScratchView.OnScratchCallback() {
27 |
28 | @Override
29 | public void onScratch(float percentage) {
30 | updatePercentage(percentage);
31 | }
32 |
33 | @Override
34 | public void onDetach(boolean fingerDetach) {
35 | if(mPercentage > 50){
36 | scratchView.setScratchAll(true);
37 | updatePercentage(100);
38 | }
39 | }
40 | });
41 |
42 | updatePercentage(0f);
43 | }
44 |
45 | protected void updatePercentage(float percentage) {
46 | mPercentage = percentage;
47 | String percentage2decimal = String.format("%.2f", percentage) + " %";
48 | percentageView.setText(percentage2decimal);
49 | }
50 |
51 | @Override
52 | public boolean onCreateOptionsMenu(Menu menu) {
53 | // Inflate the menu; this adds items to the action bar if it is present.
54 | getMenuInflater().inflate(R.menu.activity_main, menu);
55 | return true;
56 | }
57 |
58 | public void onClickHandler(View view){
59 | switch(view.getId()){
60 | case R.id.reset_button:
61 | scratchView.resetView();
62 | scratchView.setScratchAll(false); // todo: should include to resetView?
63 | updatePercentage(0f);
64 | break;
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/testWScratchView/src/com/winsontan520/testwscratchview/Demos.java:
--------------------------------------------------------------------------------
1 | package com.winsontan520.testwscratchview;
2 |
3 | import java.text.Collator;
4 | import java.util.ArrayList;
5 | import java.util.Collections;
6 | import java.util.Comparator;
7 | import java.util.HashMap;
8 | import java.util.List;
9 | import java.util.Map;
10 |
11 | import android.app.ListActivity;
12 | import android.content.Intent;
13 | import android.content.pm.PackageManager;
14 | import android.content.pm.ResolveInfo;
15 | import android.os.Bundle;
16 | import android.view.View;
17 | import android.widget.ListView;
18 | import android.widget.SimpleAdapter;
19 |
20 | public class Demos extends ListActivity {
21 |
22 | @Override
23 | public void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 |
26 | Intent intent = getIntent();
27 | String path = intent.getStringExtra("com.example.android.apis.Path");
28 |
29 | if (path == null) {
30 | path = "";
31 | }
32 |
33 | setListAdapter(new SimpleAdapter(this, getData(path), android.R.layout.simple_list_item_1, new String[] { "title" }, new int[] { android.R.id.text1 }));
34 | getListView().setTextFilterEnabled(true);
35 | }
36 |
37 | protected List