Android实现抽奖转盘
一、SurfaceView認識及的應用的思路
SurfaceView繼承自(extends)View,View是在UI線程中進行繪制;
而SurfaceView是在一個子線程中對自己進行繪制,優勢:避免造成UI線程阻塞;
SurfaceView中包含一個專門用于繪制的Surface,Surface中包含一個Canvas;
獲得Canvas:可以從SurfaceView中方法的getHolder()獲得SurfaceHolder,從holder獲得Canvas;
holder還管理著SurfaceView的生命周期:
①surfaceCreated()創建子線程,子線程的run()方法中開啟SurfaceView的繪制。
②surfaceChanged()。
③surfaceDestoryed()中關閉子線程。
二、SurfaceView的一般寫法
1 package com.example.luckypan;
2
3 import android.content.Context;
4 import android.graphics.Canvas;
5 import android.util.AttributeSet;
6 import android.view.SurfaceHolder;
7 import android.view.SurfaceHolder.Callback;
8 import android.view.SurfaceView;
9
10 public class SurfaceViewTemplate extends SurfaceView implements Callback, Runnable {
11
12 private SurfaceHolder mHolder;
13 private Canvas mCanvas;
14 /**
15 * 用于繪制線程
16 */
17 private Thread thread;
18 /**
19 * 線程的控制開關
20 */
21 private boolean isRunning;
22 public SurfaceViewTemplate(Context context) {
23 this(context, null);
24 }
25 public SurfaceViewTemplate(Context context, AttributeSet attrs) {
26 super(context, attrs);
27 mHolder=getHolder();
28 mHolder.addCallback(this);
29 //可獲得焦點
30 setFocusable(true);
31 setFocusableInTouchMode(true);
32 //設置常量
33 setKeepScreenOn(true);
34 }
35 public void surfaceCreated(SurfaceHolder holder) {
36 isRunning=true;
37 thread=new Thread(this);
38 thread.start();
39
40 }
41 public void surfaceChanged(SurfaceHolder holder, int format, int width,
42 int height) {
43 // TODO Auto-generated method stub
44
45 }
46 public void surfaceDestroyed(SurfaceHolder holder) {
47 isRunning=false;
48
49 }
50 public void run() {
51 //不斷進行繪制
52 while (isRunning)
53 {
54 draw();
55 }
56 }
57 private void draw() {
58 try {
59 mCanvas=mHolder.lockCanvas();
60 if (mCanvas!=null) {
61 //
62 }
63 }
64 catch (Exception e) {
65
66 }
67 finally
68 {
69 if (mCanvas!=null) {
70 mHolder.unlockCanvasAndPost(mCanvas);
71 }
72 }
73 }
74
75
76 }
SurfaceViewTemplate
三、代碼編寫
繪制抽獎轉盤的盤快
繪制背景:drawBg(), Canvas的兩個方法:drawColor(color the color to draw onto the canvas),這里我設置背景色為白色0xFFFFFFFF、drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint),這個bitmap是背景圖片,背景是一個矩形new Rect(),其他參數設置為null。
1 private void drawBg() {
2 mCanvas.drawColor(0xFFFFFFFF);
3 mCanvas.drawBitmap(mBgBitmap, null, new Rect(mPadding/2, mPadding/2, getMeasuredWidth()-mPadding/2, getMeasuredHeight()-mPadding/2), null);
4 }
drawBg
繪制盤快:
1 //繪制盤快
2 float tmpAngle=mStartAngle;
3 float sweepAngle=360/mItemCount;
4 for (int i = 0; i < mItemCount; i++) {
5 mArcPaint.setColor(mColor[i]);
6 //繪制盤快
7 mCanvas.drawArc(mRange, tmpAngle, sweepAngle,true, mArcPaint);
View Code
繪制抽獎轉盤的獎項文字
1 /**
2 * 繪制每個盤快的文本
3 * @param tmpAngle
4 * @param sweepAngle
5 * @param string
6 */
7 private void drawText(float tmpAngle, float sweepAngle, String string) {
8 Path path=new Path();
9 path.addArc(mRange, tmpAngle, sweepAngle);
10 //利用水平偏移量讓文字居中
11 float textWidth=mTextPaint.measureText(string);
12 int hOffset=(int) (mRadius*Math.PI/mItemCount/2-textWidth/2);
13 int vOffset=mRadius/2/6;//垂直偏移量
14 mCanvas.drawTextOnPath(string, path, hOffset, vOffset, mTextPaint);
15 }
drawText
繪制抽獎轉盤的圖片
1 /**
2 * 繪制圖片
3 * @param tmpAngle
4 * @param bitmap
5 */
6 private void drawIcon(float tmpAngle, Bitmap bitmap) {
7 //設置圖片的寬度為直徑的1/8
8 int imgWidth=mRadius/8;
9 float angle=(float) ((tmpAngle+360/mItemCount/2)*Math.PI/180);
10 int x=(int) (mCenter+mRadius/2/2*Math.cos(angle));
11 int y=(int) (mCenter+mRadius/2/2*Math.sin(angle));
12 //確定圖片位置
13 Rect rect=new Rect(x-imgWidth/2, y-imgWidth/2, x+imgWidth/2, y+imgWidth/2);
14 mCanvas.drawBitmap(bitmap, null, rect,null);
15 }
drawIcon
轉盤滾動及設置停止的指向
1 private void draw() {
2 try {
3 mCanvas=mHolder.lockCanvas();
4 if (mCanvas!=null) {
5 //繪制背景
6 drawBg();
7 //繪制盤快
8 float tmpAngle=mStartAngle;
9 float sweepAngle=360/mItemCount;
10 for (int i = 0; i < mItemCount; i++) {
11 mArcPaint.setColor(mColor[i]);
12 //繪制盤快
13 mCanvas.drawArc(mRange, tmpAngle, sweepAngle,true, mArcPaint);
14 //繪制文本
15 drawText(tmpAngle,sweepAngle,mStrings[i]);
16 //繪制圖片
17 drawIcon(tmpAngle,mImagBitmaps[i]);
18 tmpAngle+=sweepAngle;
19 }
20 mStartAngle+=mSpeed;
21 //判斷是否點擊停止按鈕
22 if (isShouldEnd) {
23 mSpeed-=1;
24 }
25 if (mSpeed<=0)
26 {
27 mSpeed=0;
28 isShouldEnd=false;
29 }
30 }
31 }
32 catch (Exception e) {
33
34 }
35 finally
36 {
37 if (mCanvas!=null) {
38 mHolder.unlockCanvasAndPost(mCanvas);
39 }
40 }
41 }
draw
四、抽獎轉盤的秘密
1 /**
2 * 電機啟動旋轉
3 * 控制指定盤快停止范圍
4 * @param index
5 */
6 public void luckyStart(int index)
7 {
8 //計算每一項的角度
9 float angle=360/mItemCount;
10 //計算每一項的中獎范圍
11 //1->150~210
12 //0->210~270
13 float from=270-(index+1)*angle;
14 float end=from+angle;
15 // 設置停下來需要旋轉的距離
16 float targetFrom=4*360+from;
17 float targetEnd=4*360+end;
18 /**
19 * <pre>
20 * v1->0 且每次-1
21 * (v1+0)*(v1+1)/2=targetFrom 等差數列求和公式;
22 * v1*v1+v1-2*targetFrom=0;
23 * v1=(-1+Math.sqrt(1+8*targetFrom))/2 一元二次方程求根公式
24 * </pre>
25 */
26 float v1=(float) ((-1+Math.sqrt(1+8*targetFrom))/2);
27 float v2=(float) ((-1+Math.sqrt(1+8*targetEnd))/2);
28 mSpeed=v1+Math.random()*(v2-v1);
29 // mSpeed=v2;
30 isShouldEnd=false;
31 }
luckyStart
總結
以上是生活随笔為你收集整理的Android实现抽奖转盘的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 应用程序无法正常启动0xc0150002
- 下一篇: 0是整数吗(零是不是整数和自然数)