本文主要实现的是一个转盘游戏,并且可以调整中奖概率。其实这个主要的实现方式就是继承SurfaceView来实现试图绘制。
话不多说,直接上源码:
MySuraceView.java(主要用与绘制转盘界面和转盘逻辑)
package com.jt.study; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Rect; import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.view.SurfaceHolder; import android.view.SurfaceView; /** * Created by JT on 2015/7/28. */ public class SurfaceViewTempalte extends SurfaceView implements SurfaceHolder.Callback, Runnable { private SurfaceHolder mHolder; private Canvas mCanvas; /** * */ private Thread t; /** * 线程的控制开关 */ private boolean isRunning; private int mPadding; private int mRaduis; private float mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, getResources().getDisplayMetrics()); private int mCenter; private Paint mArcPaint; private Paint bgArcPaint; private Paint mTextPaint; private int mItemCount = 6; private int[] smallImg = new int[]{R.drawable.ic_smile, R.drawable.ic_phone, R.drawable.ic_zhi, R.drawable.ic_smile, R.drawable.ic_danfan, R.drawable.ic_zhi}; private String[] strings = new String[]{"谢谢惠顾", "手机", "餐巾纸", "谢谢惠顾", "单反", "餐巾纸"}; private Bitmap[] mImageBitmap; private RectF mRectf = new RectF(); private int[] colors = new int[]{0xff33FF00, 0xffCC6699, 0xff33FF00, 0xffCC6699, 0xff33FF00, 0xffCC6699}; private volatile float mStartAngle = 0; private float mSpeed; private boolean isShouleEnd; public SurfaceViewTempalte(Context context) { super(context, null); } public SurfaceViewTempalte(Context context, AttributeSet attrs) { super(context, attrs); mHolder = getHolder(); mHolder.addCallback(this); setFocusable(true); setFocusableInTouchMode(true); //设置常量 setKeepScreenOn(true); } public SurfaceViewTempalte(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public void surfaceCreated(SurfaceHolder holder) { Log.d(TAG, "surfaceCreated"); //初始化盘快的画笔 mArcPaint = new Paint(); mArcPaint.setAntiAlias(true); mArcPaint.setDither(true); //初始化盘块背景图片 bgArcPaint = new Paint(); bgArcPaint.setAntiAlias(true); bgArcPaint.setDither(true); bgArcPaint.setColor(Color.RED); //初始化绘制盘块的文本画笔 mTextPaint = new Paint(); mTextPaint.setColor(0xffffffff); mTextPaint.setTextSize(mTextSize); //初始化盘块的绘制范围 mRectf = new RectF(mPadding, mPadding, mPadding + mRaduis, mPadding + mRaduis); //初始化图片 mImageBitmap = new Bitmap[mItemCount]; for (int i = 0; i < mImageBitmap.length; i++) { mImageBitmap[i] = BitmapFactory.decodeResource(getResources(), smallImg[i]); } isRunning = true; t = new Thread(this); t.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { isRunning = false; } @Override public void run() { while (isRunning) { long start = System.currentTimeMillis(); draw(); long end = System.currentTimeMillis(); if (end - start < 50) { try { Thread.sleep(50 - (end - start)); } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * 绘制 */ private void draw() { try { mCanvas = mHolder.lockCanvas(); if (mCanvas != null) { // mCanvas.drawArc(mRectf); drawBg(); float tmpAngle = mStartAngle; float sweepAngle = 360 / mItemCount; for (int i = 0; i < mItemCount; i++) { mArcPaint.setColor(colors[i]); mCanvas.drawArc(mRectf, tmpAngle, sweepAngle, true, mArcPaint); drawText(tmpAngle, sweepAngle, strings[i]); drawIcon(tmpAngle, BitmapFactory.decodeResource(getResources(), smallImg[i])); tmpAngle = sweepAngle + tmpAngle; } mStartAngle += mSpeed; Log.d(TAG, "mstartAngle " + mStartAngle); //判断是否点击停止按钮 if (isShouleEnd) { mSpeed -= 1; drawStart("结束"); } else { drawStart("开始"); } if (mSpeed <= 0) { mSpeed = 0; isShouleEnd = false; } drawArrow(); } } catch (Exception e) { } finally { if (mCanvas != null ) { mHolder.unlockCanvasAndPost(mCanvas); //用于保证每次都能将内容提交 } } } /** * @param tmpAngle * @param sweepAngle * @param text 绘制模块文字 */ private void drawText(float tmpAngle, float sweepAngle, String text) { Path path = new Path(); path.addArc(mRectf, tmpAngle, sweepAngle); int textWidth = (int) mTextPaint.measureText(text); int hOffset = (int) (mRaduis * Math.PI / mItemCount / 2 - textWidth / 2); mCanvas.drawTextOnPath(text, path, hOffset, mRaduis / 9, mTextPaint); } /** * @param tmpAngle 偏转角度 * @param bitmap 绘制每个模块的图片 */ private void drawIcon(float tmpAngle, Bitmap bitmap) { int imgWidth = mRaduis / 8; float angle = (float) ((tmpAngle + 360 / mItemCount / 2) * Math.PI / 180); int x = (int) (mCenter + mRaduis / 4 * Math.cos(angle)); int y = (int) (mCenter + mRaduis / 4 * Math.sin(angle)); Rect rect = new Rect(x - imgWidth / 2, y - imgWidth / 2, x + imgWidth / 2, y + imgWidth / 2); mCanvas.drawBitmap(bitmap, null, rect, null); }
/** * 绘制背景圆圈 */ private void drawBg() { Log.d(TAG, "drawBg"); mCanvas.drawColor(Color.WHITE); mCanvas.drawArc(new RectF(mPadding / 2, mPadding / 2, getMeasuredWidth() - mPadding / 2, getMeasuredHeight()
- mPadding / 2), 0, 360, true, bgArcPaint); } /** * 绘制箭头 */ private void drawArrow() { Paint paint = new Paint(); paint.setColor(Color.RED); paint.setStyle(Paint.Style.FILL); paint.setStrokeWidth(5); mCanvas.drawLine(mCenter, mCenter, mCenter, mCenter - mRaduis / 4, paint); Path path = new Path(); paint.setStyle(Paint.Style.STROKE); path.moveTo(mCenter - 10, mCenter - mRaduis / 5); path.lineTo(mCenter, mCenter - mRaduis / 4); path.lineTo(mCenter + 10, mCenter - mRaduis / 5); mCanvas.drawPath(path, paint); } /** * @param text 绘制中间开始按钮 */ public void drawStart(String text) { Paint paint = new Paint(); paint.setColor(Color.RED); paint.setAntiAlias(true); mCanvas.drawCircle(mCenter, mCenter, 40, paint); paint.reset(); paint.setColor(Color.WHITE); paint.setTextSize(mTextSize); paint.setAntiAlias(true); mCanvas.drawText(text, mCenter - paint.measureText(text) / 2, mCenter + paint.measureText(text) / 5, paint); } private final static String TAG = "SurfaceViewTempalate"; @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { Log.d(TAG, "onMeasure"); super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = Math.min(getMeasuredWidth(), getMeasuredHeight()); mRaduis = width - getPaddingLeft() * 2;//直径 mCenter = width / 2;//中心点 mPadding = getPaddingLeft(); setMeasuredDimension(width, width); } /** * 开始转盘 index是表示你想抽中的那个选项的位置 */ public void luckStart(int index) { int angle = 360 / mItemCount;//每一项的角度 //计算每一项中奖范围(当前index) 如果index=1对应的是150~210度 float from = 270 - (index + 1) * angle;//最小角度 float end = from + angle;//最大角度 float targetFrom = 4 * 360 + from;//点击停止之后,需要转的最小角度 float targetEnd = 4 * 360 + end;//点击停止之后,需要转的最大角度 float v1 = (float) ((-1 + Math.sqrt(1 + 8 * targetFrom)) / 2);//最小速度 float v2 = (float) ((-1 + Math.sqrt(1 + 8 * targetEnd)) / 2);//最大速度 mSpeed = (float) (v1 + Math.random() * (v2 - v1));//在这两者速度之间都能抽中该选项 isShouleEnd = false; } /** * 停止转盘 */ public void luckEnd() { mStartAngle = 0; isShouleEnd = true; } /** * @return 转盘是否在旋转 */ public boolean isStart() { return mSpeed != 0; } /** * @return 转盘是否被点击成了停止 */ public boolean isShouleEnd() { return isShouleEnd; } }
package com.jt.study; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; public class MainActivity extends Activity { private SurfaceViewTempalte surfaceViewTempalte; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); surfaceViewTempalte = (SurfaceViewTempalte) findViewById(R.id.surfice); surfaceViewTempalte.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!surfaceViewTempalte.isStart()) { surfaceViewTempalte.luckStart(0); } else { if (!surfaceViewTempalte.isShouleEnd()) { surfaceViewTempalte.luckEnd(); } } } } ); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }