安卓:制作一个刮奖控件

1.创建自定义控件,如果要显示文字则继承TextView。

2.设置好画笔的颜色,粗细,空心还是实心,透明度,有无锯齿,等参数。

3.画笔还要设置交叉颜色的类型。

4.从资源图片获得覆盖奖品图片的图案。

  1 package com.example.scratcharea;
  2 
  3 import com.example.scratcharea.ScratchController.OnScratchListener;
  4 
  5 import android.R.drawable;
  6 import android.R.integer;
  7 import android.app.ActionBar.LayoutParams;
  8 import android.content.Context;
  9 import android.content.res.Resources;
 10 import android.content.res.TypedArray;
 11 import android.graphics.Bitmap;
 12 import android.graphics.Bitmap.Config;
 13 import android.graphics.BitmapFactory;
 14 import android.graphics.Canvas;
 15 import android.graphics.Color;
 16 import android.graphics.Matrix;
 17 import android.graphics.Paint;
 18 import android.graphics.Path;
 19 import android.graphics.PorterDuff;
 20 import android.graphics.PorterDuffXfermode;
 21 import android.graphics.drawable.BitmapDrawable;
 22 import android.graphics.drawable.Drawable;
 23 import android.os.Handler;
 24 import android.os.Message;
 25 import android.util.AttributeSet;
 26 import android.util.Log;
 27 import android.view.MotionEvent;
 28 import android.view.ViewGroup;
 29 import android.widget.ImageView;
 30 import android.widget.Toast;
 31 import android.media.AudioManager;
 32 import android.media.SoundPool;
 33 
 34 public class ScratchController extends ImageView{
 35 
 36     private Context context;
 37     private Paint pen;
 38     private Path drawPath;
 39     private Paint bitmapPen;
 40 
 41     private Canvas canvas;
 42     private float mx,my;
 43     private SoundPool sp;
 44     int scratchSound;
 45     int streamId;
 46     boolean isplaying=false;
 47     OnScratchListener scratchListener;
 48     boolean canCalculate=false;
 49     
 50     private Bitmap maskbitmap;
 51     
 52     int picWidth;
 53     int picHeight;
 54     
 55     int maskWidth;
 56     int maskHeight;
 57     
 58     int picColorPixels;
 59     int maskColorPixels;
 60     
 61     public interface OnScratchListener{//事件监听接口
 62         void onScratch(int persent);
 63     }
 64     
 65     public void setOnScratchListener(OnScratchListener listener){
 66         this.scratchListener =  listener;
 67     }
 68     
 69     Handler scratchHandler = new Handler(){
 70         public void handleMessage(Message msg){
 71             if(scratchListener!=null){
 72                 int persent = msg.arg1;
 73                 scratchListener.onScratch(persent);
 74             }
 75         }
 76     };
 77     
 78     Runnable calMaskRunnable = new Runnable() {
 79         
 80         @Override
 81         public void run() {
 82             maskColorPixels=calColorPixels(maskbitmap);//计算所有有色像素的个数
 83     //    Log.i("calMaskRunnable","maskColorPixels:"+maskColorPixels);
 84         }
 85     };
 86     
 87     Runnable calPercentRunnable = new Runnable() {
 88         
 89         @Override
 90         public void run() {
 91             if(canCalculate){//计算后来的有色像素和初始有色像素的比值并增大100倍。。。
 92                 int colorPixels=calColorPixels(maskbitmap);
 93             //    Log.i("calMaskRunnable","colorPixels: "+colorPixels);
 94                 int percent =100-(int)((colorPixels*1.0/maskColorPixels)*100);
 95                 Message msg= scratchHandler.obtainMessage();//从message pool中获取一个message 并且将message 的target属性指向改handler
 96                 msg.arg1 =percent;//
 97                 scratchHandler.sendMessage(msg);
 98             }
 99         }
100     };
101     
102     private int calColorPixels(Bitmap bitmap){
103         int colorPixels = 0;
104         int w=bitmap.getWidth();
105         int h=bitmap.getHeight();
106         int arrLen = w*h;
107         int [] pixels = new int [arrLen];
108     //    Log.i("calColorPixels","w: "+w+" h: "+h);
109         bitmap.getPixels(pixels, 0, w, 0, 0, w, h);//获取像素的点
110         for(int i=0;i<arrLen;i++){
111             if(pixels[i]!=0){
112                 colorPixels++;
113             }
114         }
115         return colorPixels;
116     }
117     
118     public ScratchController(Context context, AttributeSet attrs) {
119         super(context, attrs);
120         this.context=context;
121         TypedArray tArray = context.obtainStyledAttributes(attrs, R.styleable.ScratchArea);
122         int len = tArray.length();
123         for(int i=0;i<len;i++){
124             if(R.styleable.ScratchArea_pic==tArray.getIndex(i)){
125                 int id = tArray.getResourceId(R.styleable.ScratchArea_pic, 0);
126                 if(id!=0){
127                     setPic(id);
128                 }
129             }
130             if(R.styleable.ScratchArea_mask==tArray.getIndex(i)){
131                 int id = tArray.getResourceId(R.styleable.ScratchArea_mask, 0);
132                 if(id!=0){
133                     if(id!=0){
134                         setMask(id);
135                     }
136                 }
137             }
138         }
139         tArray.recycle();
140     }
141         
142     public void setPic(int resId){
143         this.setImageResource(resId);
144         this.setScaleType(ImageView.ScaleType.FIT_XY);
145 //        ViewGroup.LayoutParams params = this.getLayoutParams();
146 //        picWidth = params.width;
147 //        picHeight = params.height;
148     }
149     
150     @Override
151     public void setLayoutParams(ViewGroup.LayoutParams params){
152         super.setLayoutParams(params);
153         picWidth = params.width;
154         picHeight = params.height;
155     }
156     
157     public void startInit(){
158         init();
159     }
160     private void init() {
161         pen = new Paint();
162         pen.setAntiAlias(true);//抗锯齿
163         //pen.setAlpha(220);//设置透明度
164         pen.setDither(true);//设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰  
165         //pen.setColor(Color.WHITE);
166         pen.setStyle(Paint.Style.STROKE);
167         pen.setStrokeWidth(35);
168         pen.setStrokeJoin(Paint.Join.ROUND);//前端是圆的
169         pen.setStrokeCap(Paint.Cap.ROUND);//后端是圆的
170         pen.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));//设置颜色交叉模式为清除
171         
172         bitmapPen=new Paint();
173         drawPath = new Path();
174         
175         
176         
177         
178         canvas = new Canvas(maskbitmap);
179         //canvas.drawColor(maskColor);
180         sp= new SoundPool(1,AudioManager.STREAM_SYSTEM,3);//
181         scratchSound = sp.load(this.getContext(), R.raw.scratch3,1);
182         
183         canCalculate= false;
184     }
185     
186     @Override
187     protected void onDraw(Canvas canvas) {
188         super.onDraw(canvas);
189         
190         this.canvas.drawPath(drawPath, pen);
191         canvas.drawBitmap(maskbitmap, 0, 0, bitmapPen);
192     }
193 
194     @Override
195     public boolean onTouchEvent(MotionEvent event) {//事件处理函数
196         switch (event.getAction()){
197         case MotionEvent.ACTION_DOWN:
198             touchDown(event);
199             //Toast.makeText(this.context, "touchDown", Toast.LENGTH_SHORT).show();
200             break;
201         case MotionEvent.ACTION_MOVE:
202             touchMove(event);
203             //Toast.makeText(this.context, "touchMove", Toast.LENGTH_SHORT).show();
204             break;
205         case MotionEvent.ACTION_UP:
206             touchUp(event);
207             break;
208         default:
209             break;
210         }
211         return true;
212     }
213 
214     private void touchUp(MotionEvent event) {
215         if(isplaying){
216             sp.stop(streamId);
217             isplaying = false;
218         }
219         canCalculate = true;
220         new Thread(calPercentRunnable).start();
221     }
222 
223     private void touchMove(MotionEvent event) {
224 
225     //Toast.makeText(this.context, "touchMove", Toast.LENGTH_SHORT).show();
226         
227         float preX=mx;
228         float preY=my;
229         mx = event.getX();
230         my = event.getY();
231         
232         if(Math.abs(preX-mx)>1||Math.abs(preY-my)>1){
233             
234             float cx=(preX+mx)/2;
235             float cy=(preY+my)/2;
236             
237             drawPath.quadTo(cx, cy, mx, my);//贝塞尔曲线平滑处理
238             if(!isplaying)
239               streamId = sp.play(scratchSound, 1, 1, 0, -1, (float)0.5);
240             isplaying =true;
241             invalidate();
242         }
243         
244     }
245 
246     private void touchDown(MotionEvent event) {
247         
248     //    Toast.makeText(this.context, "touchDown", Toast.LENGTH_SHORT).show();
249         mx=event.getX();
250         my=event.getY();
251         
252         drawPath.reset();
253         drawPath.moveTo(mx, my);
254         
255     }
256     
257     public void setMask(int mask){
258         Resources res = getResources();
259         maskbitmap = BitmapFactory.decodeResource(res, mask).copy(Bitmap.Config.ARGB_8888, true);
260       // bitmap = Bitmap.createBitmap(480, 800, Config.ARGB_8888);
261         int width = maskbitmap.getWidth();
262         //Log.i("ScratchController",""+width);
263         //Toast.makeText(this.context, width, Toast.LENGTH_LONG).show();
264         int height = maskbitmap.getHeight();
265         //Log.i("ScratchController","height:"+height);
266     
267         maskWidth=picWidth;
268         //Log.i("ScratchController","maskWidth:"+maskWidth);
269         maskHeight =picHeight;
270         //Log.i("ScratchController","maskHeight:"+maskHeight);
271         
272         float scaleWidth = ((float)maskWidth)/width;
273         float scaleHeight = ((float)maskHeight)/height;
274         Matrix matrix = new Matrix();
275         matrix.postScale(scaleWidth, scaleHeight);//放缩变换
276         maskbitmap = Bitmap.createBitmap(maskbitmap,0,0,width,height,matrix,true);//以maskbitmap为模板创建bitmap
277         
278         new Thread(calMaskRunnable).start();
279     }
280 
281     
282 }
原文地址:https://www.cnblogs.com/jackwuyongxing/p/3819419.html