1.自定义surfaceView
package com.example.administrator.myapplication; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; 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 Administrator on 2017/8/2 0002. */ public class SurfaceViewTemPlate extends SurfaceView implements SurfaceHolder.Callback, Runnable { private SurfaceHolder mHolder; private Canvas mCanvas; /** * 用于绘制线程 */ private Thread t; /** * 控制线程的开关 */ private boolean isRunning; /** * 抽奖文字(盘块的奖项) */ private String[] mStrs = new String[]{"单反相机", "恭喜发财", "iPad", "iPhone", "服装一套", "恭喜发财"}; /** * 抽奖图片 */ private int[] mImgs = new int[]{R.drawable.danfan, R.drawable.f040, R.drawable.ipad, R.drawable.iphone, R.drawable.meizi, R.drawable.f040}; /** * 与抽奖图片对应的bitmap数组 */ private Bitmap[] mImgsBitmap; /** * 抽奖盘块颜色,对应6个盘块 */ private int[] mColors = new int[]{0xFFFFC300, 0xFFF17E01, 0xFFFFC300, 0xFFF17E01, 0xFFFFC300, 0xFFF17E01}; private int mItemCount = 6; /** * 整个盘块的范围 */ private RectF mRange; /** * 盘块的直径 */ private int mRadius; /** * 绘制盘块的画笔 */ private Paint mArcPaint; /** * 绘制文本的画笔 */ private Paint mTextPaint; /** * 滚动的速度 */ private double mSpeed; /** * 起始角度 volatile:保证线程间变量的可见性 */ private volatile float mStartAngle = 0; /** * 判断是否点击了停止按钮 */ private boolean isShouldEnd; /** * 整个中心位置 */ private int mCenter; /** * 转盘的padding 这里我们的padding取四个padding的最小值(或者直接以paddingleft为准) */ private int mPadding; /** * 设置抽奖盘的背景 */ private Bitmap mBgBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.bg2); /** * 设置盘块字体大小 */ private float mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,20,getResources().getDisplayMetrics()); private boolean isEnd; public SurfaceViewTemPlate(Context context) { this(context, null); } public SurfaceViewTemPlate(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SurfaceViewTemPlate(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mHolder = getHolder(); mHolder.addCallback(this); //设置可点击 setFocusable(true); setFocusableInTouchMode(true); //设置常量 setKeepScreenOn(true); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int with = Math.min(getMeasuredWidth(),getMeasuredHeight()); Log.e("zm","with:"+with); mPadding = getPaddingLeft(); Log.e("zm","mPadding:"+mPadding); //直径 mRadius = with - mPadding*2; //中心点位置 mCenter = with/2; setMeasuredDimension(with,with); } @Override public void surfaceCreated(SurfaceHolder surfaceHolder) { //初始化绘制盘块的画笔 mArcPaint = new Paint(); //设置抗锯齿 mArcPaint.setAntiAlias(true); mArcPaint.setDither(true); //初始化绘制文字的画笔 mTextPaint = new Paint(); mTextPaint.setColor(0xFFFFFFFF); mTextPaint.setTextSize(mTextSize); //初始化盘块的范围 mRange = new RectF(mPadding,mPadding,mPadding+mRadius,mPadding+mRadius); //初始化图片 mImgsBitmap = new Bitmap[mItemCount]; for (int i = 0;i<mItemCount;i++){ mImgsBitmap[i] = BitmapFactory.decodeResource(getResources(),mImgs[i]); } isRunning = true; t = new Thread(this); t.start(); } @Override public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { } @Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { isRunning = false; } @Override public void run() { //持续绘制 while (isRunning) { long start = System.currentTimeMillis(); draw(); long end = System.currentTimeMillis(); //50ms绘制一次 if(end - start < 50){ try { Thread.sleep(50-(end - start)); } catch (InterruptedException e) { e.printStackTrace(); } } } } private void draw() { //try catch 是为了处理点击home和返回键的问题 try { mCanvas = mHolder.lockCanvas(); if (mCanvas != null) { //绘制背景 drawBg(); //绘制每个盘块 float tempAngle = mStartAngle; float sweepAngle = 360/mItemCount; for(int i = 0;i<mItemCount;i++){ mArcPaint.setColor(mColors[i]); mCanvas.drawArc(mRange,tempAngle,sweepAngle,true,mArcPaint); //绘制文本 drawText(tempAngle,sweepAngle,mStrs[i]); //绘制icon drawIcon(tempAngle,mImgsBitmap[i]); tempAngle = tempAngle+sweepAngle; } mStartAngle+=mSpeed; if(isShouldEnd){ mSpeed--; } if(mSpeed<=0){ mSpeed = 0; isShouldEnd = false; } } } catch (Exception e) { } finally { //释放mCanvas if (mCanvas != null) { mHolder.unlockCanvasAndPost(mCanvas); } } } /** * 绘制每个板块的icon * @param tempAngle * @param bitmap */ private void drawIcon(float tempAngle, Bitmap bitmap) { //规定图片的宽度 int imgWith = mRadius/8; //绘制每个图片的起始弧度 double angle = (tempAngle+360/mItemCount/2)*Math.PI/180; //拿到图片中心点的位置 int x = (int) (mCenter+mRadius/4*Math.cos(angle)); int y = (int) (mCenter+mRadius/4*Math.sin(angle)); //规定绘制范围 Rect rect = new Rect(x-imgWith/2,y-imgWith/2,x+imgWith/2,y+imgWith/2); mCanvas.drawBitmap(bitmap,null,rect,null); } /** * 绘制每个盘块的文字 * @param tempAngle * @param sweepAngle * @param mStr */ private void drawText(float tempAngle, float sweepAngle, String mStr) { //绘制弧形 Path path = new Path(); path.addArc(mRange,tempAngle,sweepAngle); float textWith = mTextPaint.measureText(mStr); //利用水平偏移量让文字居中 hOffset水平偏移量 每个盘块弧长的一半减去文字宽度的一半 float hOffset = (float) (mRadius*Math.PI/mItemCount/2-textWith/2); //垂直偏移量 float vOffset = mPadding; mCanvas.drawTextOnPath(mStr,path,hOffset,vOffset,mTextPaint); } /** * 绘制背景 */ private void drawBg() { mCanvas.drawColor(0xFFFFFFFF); Log.e("zm","getMeasuredWidth:"+getMeasuredWidth()); mCanvas.drawBitmap(mBgBitmap,null,new Rect(mPadding/2,mPadding/2,getMeasuredWidth()-mPadding/2,getMeasuredHeight()-mPadding/2),null); } /** * 点击启动旋转 * @param index 指定抽奖项 */ public void start(int index){ //指定每一项的角度 float angle = 360/mItemCount; //计算每一项中奖范围(当前index) //1 -> 150 - 210 //0 -> 210 - 270 float from = 270 - (index+1) * angle; float end = from + angle; //设置停下来需要旋转的距离 float targetFrom = 4 * 360 + from; float targetEnd = 4 * 360 + end; /** * v1 起始位置的速度 * v2 终点位置的速度 */ float v1 = (float) ((-1 + Math.sqrt(1+8 * targetFrom))/2); float v2 = (float) ((-1 + Math.sqrt(1+8 * targetEnd))/2); //此处mSpeed的值是v1 -> v2之间的一个值 mSpeed = v1 + Math.random()*(v2-v1); isShouldEnd = false; } /** * 点击地址旋转 */ public void end(){ mStartAngle = 0; isShouldEnd = true; } /** * 转盘是否在旋转 * @return */ public boolean isPanRunning(){ return mSpeed!=0; } /** * 停止按钮是否按下 * @return */ public boolean isShouldEnd() { return isShouldEnd; } }2.布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:background="#ffffff" android:layout_height="match_parent" > <com.example.administrator.myapplication.SurfaceViewTemPlate android:padding="30dp" android:id="@+id/luck_pan" android:layout_width="match_parent" android:layout_centerInParent="true" android:layout_height="match_parent" > </com.example.administrator.myapplication.SurfaceViewTemPlate> <ImageView android:id="@+id/click_start" android:layout_width="150dp" android:layout_height="150dp" android:layout_centerInParent="true" android:src="@drawable/start" /> </RelativeLayout>3.MainActivity
package com.example.administrator.myapplication; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import java.util.Random; public class MainActivity extends AppCompatActivity { private String[] mVals = new String[] { "Hello", "Android", "Weclome Hi ", "Button", "TextView", "Hello", "Android", "Weclome", "Button ImageView", "TextView", "Helloworld", "Android", "Weclome Hello", "Button Text", "TextView" }; private FlowLayout mFlowLayout; private ImageView click_start; private SurfaceViewTemPlate luck_pan; int index; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //mFlowLayout = (FlowLayout) findViewById(R.id.id_flowlayout); click_start = (ImageView) findViewById(R.id.click_start); luck_pan = (SurfaceViewTemPlate) findViewById(R.id.luck_pan); click_start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(!luck_pan.isPanRunning()){ setProbability(); luck_pan.start(index); click_start.setImageResource(R.drawable.stop); }else{ //转盘还在转,判断我们的停止按钮还没有按的话,点击为停止 if(!luck_pan.isShouldEnd()){ luck_pan.end(); click_start.setImageResource(R.drawable.start); } } } }); initData(); } public void initData() { /* LayoutInflater mInflater = LayoutInflater.from(this); for (int i = 0; i < mVals.length; i++) { TextView tv = (TextView) mInflater.inflate(R.layout.tv, mFlowLayout, false); tv.setText(mVals[i]); mFlowLayout.addView(tv); }*/ } /** * 设置概率 */ private void setProbability(){ int temNum = 1 + new Random().nextInt(1000);//1-1000 if(temNum <= 30 && temNum > 0){ index = 0; }else if(temNum <= 450 && temNum > 30){ index = 1; }else if(temNum <= 700 && temNum > 450){ index = 2; }else if(temNum <= 720 && temNum > 700){ index = 3; }else if(temNum <= 800 && temNum > 720){ index = 4; }else if(temNum <= 1000 && temNum > 800){ index = 5; } } }