先来看看布局页面 so easy 简简单单的布局
接下来看一下 MainActivity 主要设置了 控制转盘转动与停止的监听
package com.Lucky.luckyview;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
private Luckypan mLuckypan;
private ImageView mStartBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStartBtn = findViewById(R.id.id_start_btn);
mLuckypan = findViewById(R.id.id_luckyPan);
mStartBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!mLuckypan.isStart()){
mLuckypan.luckyStart();
mStartBtn.setImageResource(R.drawable.stop);
}else {
if (!mLuckypan.isShouldEnd()){
mLuckypan.luckyEnd();
mStartBtn.setImageResource(R.drawable.start);
}
}
}
});
}
}
接下来就是重头戏了 抽奖转盘的 一些功能实现 文字 图片 …
package com.Lucky.luckyview;
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.TypedValue;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/**
* date:2018/11/3
* author:李壮(MR.da)
* function:
*/
public class Luckypan extends SurfaceView implements SurfaceHolder.Callback,Runnable {
private SurfaceHolder mHolder;
private Canvas mCanvas;
//用于绘制的线程
private Thread t;
//用于控制线程的开关
private boolean isRunning;
//盘块的文字
private String[] mStrs = new String[]{"单反相机","IPAD","恭喜发财","IPONE","服装一套","恭喜发财"};
//盘块的图片
private int[] mImgs = new int[]{R.drawable.danfan,R.drawable.ipad,R.drawable.f015,R.drawable.iphone,R.drawable.meizi,R.drawable.f015};
//与图片对应的bitmap数组
private Bitmap[] mImgsBitmap;
//盘块的颜色
private int[] mColor = new int[]{0xFFFFC300,0xFFF17E01,0xFFFFC300,0xFFF17E01,0xFFFFC300,0xFFF17E01};
private int mItemCount = 6;
//整个盘块的范围
private RectF mRange = new RectF();
//整个盘块的直径
private int mRadius;
//绘制盘块的画笔
private Paint mArcPaint;
//绘制文本的画笔
private Paint mTextPaint;
//滚动的速度
private double mSpeed;
//保证线程间的可见性
private volatile int mStartAngle = 0;
//判断是否点击了停止按钮
private boolean isShouldEnd;
//转盘的中心位置
private int mCenter;
//这里我们的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());
public Luckypan(Context context) {
this(context,null);
}
public Luckypan(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public Luckypan(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
mHolder = getHolder();
mHolder.addCallback(this);
//可获得焦点
setFocusable(true);
setFocusableInTouchMode(true);
//设置常量
setKeepScreenOn(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = Math.min(getMeasuredWidth(), getMeasuredHeight());
mPadding = getPaddingLeft();
//直径
mRadius = width - mPadding *2;
//中心点
mCenter = width / 2;
setMeasuredDimension(width,width);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
//初始化绘制盘块的画笔
mArcPaint = new Paint();
mArcPaint.setAntiAlias(true);
mArcPaint.setDither(true);
//初始化绘制盘块的画笔
mTextPaint = new Paint();
mTextPaint.setColor(Color.WHITE);
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 holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
isRunning = false;
}
@Override
public void run() {
while (isRunning){
draw();
}
}
private void draw() {
mCanvas = mHolder.lockCanvas();
try {
if (mCanvas != null){
//绘制背景
drawBg();
//绘制盘块
float tmpAngle = mStartAngle;
float sweepAngle = 360 / mItemCount;
for (int i = 0; i < mItemCount; i++){
mArcPaint.setColor(mColor[i]);
//绘制盘块
mCanvas.drawArc(mRange,tmpAngle,sweepAngle,true,mArcPaint);
//绘制文本
drawText(tmpAngle,sweepAngle,mStrs[i]);
//绘制背景图片
drawIcon(tmpAngle,mImgsBitmap[i]);
tmpAngle += sweepAngle;
}
mStartAngle += mSpeed;
//如果点击了停止按钮
if (isShouldEnd){
mSpeed -= 1;
}
if (mSpeed <= 0){
mSpeed = 0;
isShouldEnd = false;
}
}
}finally {
if (mCanvas != null){
mHolder.unlockCanvasAndPost(mCanvas);
}
}
}
//点击了启动旋转
public void luckyStart(){
mSpeed = 50;
isShouldEnd = false;
}
//点击了停止旋转
public void luckyEnd(){
isShouldEnd = true;
}
//转盘是否在旋转
public boolean isStart() {
return mSpeed != 0;
}
public boolean isShouldEnd() {
return isShouldEnd;
}
//绘制Icon 图片
private void drawIcon(float tmpAngle, Bitmap bitmap) {
//设置图片的宽度为直径的1/8
int imgWidth = mRadius / 8;
float angle = (float) ((tmpAngle + 360 / mItemCount / 2) * Math.PI / 180);
int x = (int) (mCenter + mRadius / 2 / 2 * Math.cos(angle));
int y = (int) (mCenter + mRadius / 2 / 2 * 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 drawText(float tmpAngle, float sweepAngle, String string) {
Path path = new Path();
path.addArc(mRange,tmpAngle,sweepAngle);
//利用水平偏移量让文字居中
float textWidth = mTextPaint.measureText(string);
int hOffset = (int) (mRadius * Math.PI / mItemCount /2 - textWidth /2);
//垂直偏移量
int vOffset = mRadius /2 /6;
mCanvas.drawTextOnPath(string,path,hOffset,vOffset,mTextPaint);
}
//绘制背景
private void drawBg() {
mCanvas.drawColor(Color.WHITE);
mCanvas.drawBitmap(mBgBitmap,null,new RectF(mPadding/2,mPadding/2,getMeasuredWidth()-mPadding /2 ,getMeasuredHeight() - mPadding /2),null);
}
}
最终看一下效果图吧