surfaceView绘制转盘抽奖

surfaceView extends View

View在UI线程绘制,surfaceView在子线程绘制,可以避免造成UI线程阻塞。

surfaceView中包含一个surface,surface中包含Canvas.

如何获取Canvas?
getHolder -> surfaceHolder
surfaceHolder -> Canvas

surfaceHolder功能:
获取Canvas,以及管理surfaceView的生命周期(surfaceGreated,surfaceChange,surfaceDestory)

绘制转盘抽奖源码:

package com.lwang.luckyturntable;

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.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.util.Random;

public class LuckyPan extends SurfaceView implements SurfaceHolder.Callback,Runnable {

    private SurfaceHolder mHolder;
    private Canvas mCanvas;

    //用于绘制的线程
    private Thread t;

    //线程控制开关
    private boolean isRunning = false;

    private String str[] = new String[]{"单反","IPAD","恭喜发财","IPHONE","服装","恭喜发财"};
    private int[] img= new int[]{R.mipmap.danfan,R.mipmap.ipad,R.mipmap.f015,R.mipmap.iphone,R.mipmap.meizi,R.mipmap.f040};
    private int[] colors = new int[]{0xFFFFC300,0xFFF17E01,0xFFFFC300,0xFFF17E01,0xFFFFC300,0xFFF17E01};

    private Bitmap[] imgBitmap;
    private int mItemCount = 6;

    /*
      整个盘块范围
     */
    private RectF mRange = new RectF();

    /*
    盘块直径
     */
    private int mRadius;

    /*
    绘制盘块的画笔
     */
    private Paint mArcPaint;
    /*
        绘制文字的画笔
         */
    private Paint mTextPaint;

    /*
    盘块滚动的速度
     */
    private double mSpeed = 0;

    /*
    起始角度
    volatile:线程间变量的可见性
     */
    private volatile float startAngle = 0;

    /*
    是否点击停止按钮
     */
    private Boolean isShouldEnd = false;

    /*
    转盘中心位置
     */
    private int mCenter;

    /*
    这里的padding 直接取4个padding的最小值  或者 以paddingleft为准
     */
    private int padding ;

    /*
    转盘背景图
     */
    private Bitmap bgBitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.bg2);

    /*
    设置文字大小为20
     */
    private float mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,20,getResources().getDisplayMetrics());

    public LuckyPan(Context context) {
        super(context,null);
    }

    public LuckyPan(Context context, AttributeSet attrs) {
        super(context, attrs);

        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());

        padding = getPaddingLeft();

        mRadius = width - padding*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(0xffffffff);
        mTextPaint.setTextSize(mTextSize);

        mRange = new RectF(padding,padding,padding+mRadius,padding+mRadius);

        imgBitmap = new Bitmap[mItemCount];
        for (int i = 0; i < mItemCount; i++) {
             imgBitmap[i] = BitmapFactory.decodeResource(getResources(),img[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){
               drawBg();
               float tmpAngle =startAngle;
               float sweepAngle = (float) 360/mItemCount;
               // mCanvas.translate(mCenter+padding,mCenter+padding);
                for (int i = 0; i < mItemCount; i++) {
                    mArcPaint.setColor(colors[i]);
                   // mCanvas.drawArc(new RectF(-mRadius/2,-mRadius/2,mRadius/2,mRadius/2),tmpAngle,sweepAngle,true,panPaint);
                    mCanvas.drawArc(mRange,tmpAngle,sweepAngle,true,mArcPaint);

                    drawTextPath(tmpAngle,sweepAngle,str[i]);

                    drawIcon(tmpAngle,imgBitmap[i]);
                    tmpAngle = tmpAngle + sweepAngle;
                }
                startAngle+=mSpeed;
                if(isShouldEnd){
                    mSpeed-=1;
                    if(mSpeed <= 0){
                        mSpeed = 0;
                        isShouldEnd = false;
                    }
                }
            }
        } catch (Exception e) {

        }finally {
            if(mCanvas != null){
                mHolder.unlockCanvasAndPost(mCanvas);
            }
        }
    }

    protected void startPan(int index){
        isShouldEnd = false;

        float angle = 360/mItemCount;
        float from = 270 - (index + 1)*angle;
        float end = from + angle;

        float targetFrom = 4*360 + from;
        float targetEnd = 4*360 + end;

        float v1 = (float) ((Math.sqrt(1+8*targetFrom)-1)/2);
        float v2 = (float) ((Math.sqrt(1+8*targetEnd)-1)/2);

        mSpeed = v1+Math.random()*(v2-v1);
        //mSpeed = v2;
    }
    protected void endPan(){
        startAngle = 0;
        isShouldEnd = true;
    }
    protected boolean isStarting(){
        if(mSpeed == 0){
           return false;
        }
        return true;
    }
    protected boolean isEnding(){
        return isShouldEnd;
    }
    private void drawIcon(float tmpAngle, Bitmap bitmap) {

//        mCanvas.translate(mCenter+padding,mCenter+padding);
//
        int imgWidth = mRadius/8;
        int imgHight = mRadius/8;

        float angle = (float) ((tmpAngle+360/mItemCount/2)*Math.PI/180);
        Log.e("LuckyPan","angle:"+angle);
        int x = (int) (mCenter+mRadius/4*Math.cos(angle));
        int y = (int) (mCenter+mRadius/4*Math.sin(angle));

        RectF rectF = new RectF(x-imgWidth/2,y-imgHight/2,x+imgWidth/2,y+imgHight/2);

        mCanvas.drawBitmap(bitmap,null,rectF,null);

    }

    private void drawTextPath(float tmpAngle, float sweepAngle, String s) {

        Path path = new Path();
        path.addArc(mRange,tmpAngle,sweepAngle);
        float mTextWidth = mTextPaint.measureText(s);
        int hOffset = (int) (mRadius*Math.PI/mItemCount/2-mTextWidth/2);
        int vOffset = mRadius/2/6;
        mCanvas.drawTextOnPath(s,path,hOffset,vOffset,mTextPaint);

    }

    /*
    绘制背景
     */
    private void drawBg() {
        mCanvas.drawColor(0xffffffff);
        mCanvas.drawBitmap(bgBitmap,null,new RectF(padding/2,padding/2,padding+mRadius+padding/2,padding+mRadius+padding/2),null);
    }
}

猜你喜欢

转载自blog.csdn.net/xdy1120/article/details/87101826