Android 自定义控件之命运之轮(抽奖转盘)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zgcqflqinhao/article/details/86241916

1 思路

首先肯定是要绘制扇形的,每一个奖品为一个扇形区分开,然后在扇形中得有当前奖品的说明,最后让这个轮盘转起来就行了。说起来很简单,但是在绘制的时候,特别是绘制文字的时候还有有一些细节需要注意的,也不是难点,只是要理清楚那些地方应该怎么去画,怎么获取需要绘制的坐标。

2 绘制扇形

首先是一些初始化工作:

public class WheelOfFortuneView extends View {
    private static final String TAG = "WheelOfFortuneView";
    private int mWidth; //控件宽,为屏幕宽和高的较小值
    private int mHeight;    //控件高,为屏幕宽和高的较小值
    private Paint mPaint;   //画笔
    private TextPaint mTextPaint;   //绘制文字的画笔
    private RectF mRectF;   //扇形绘制区域
    private Path mPath; //路径
    private PathMeasure mPathMeasure;   //路径测量的对象
    private Rect mTextBounds;   //文字绘制区域
    private float[] pos = new float[2]; //记录路径中某个点的坐标数组
    private float[] tan = new float[2];

    private List<Prize> mPrizeList = new ArrayList<>();

    public WheelOfFortuneView(Context context) {
        this(context, null);
    }

    public WheelOfFortuneView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WheelOfFortuneView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);

        mTextPaint = new TextPaint();
        mTextPaint.setAntiAlias(true);

        mRectF = new RectF();
        mPath = new Path();
        mPathMeasure = new PathMeasure();
        mTextBounds = new Rect();

        mPrizeList.add(new Prize("一等奖", Color.RED));
        mPrizeList.add(new Prize("二等奖", Color.YELLOW));
        mPrizeList.add(new Prize("三等奖", Color.BLUE));
        mPrizeList.add(new Prize("谢谢你", Color.GREEN));
        mPrizeList.add(new Prize("一等奖", Color.RED));
        mPrizeList.add(new Prize("二等奖", Color.YELLOW));
        mPrizeList.add(new Prize("三等奖", Color.BLUE));
        mPrizeList.add(new Prize("谢谢你", Color.GREEN));
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = mHeight = Math.min(getContext().getResources().getDisplayMetrics().widthPixels, getContext().getResources().getDisplayMetrics().heightPixels);
        setMeasuredDimension(mWidth, mHeight);

        //绘制扇形的区域
        mRectF.set(0, 0, mWidth, mHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

    private static int dp2px(Context context, float dpValue) {
        float density = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * density + 0.5f);
    }

    private static int sp2px(Context context, float spValue) {
        float scaleDensity = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * scaleDensity + 0.5f);
    }

    public static class Prize {
        private String text;
        private int backgroundColor;

        public Prize() {
        }

        public Prize(String text, int backgroundColor) {
            this.text = text;
            this.backgroundColor = backgroundColor;
        }

        public String getText() {
            return text;
        }


        public int getBackgroundColor() {
            return backgroundColor;
        }
    }
}

在 View 的构造方法中初始化了一些画笔、测量范围的矩形、Path 和 PathMeasure 等,然后在 onMeasure() 方法中目前是将宽高现在写死了,为屏幕宽高中的较小值,最后定义了一个简单的奖品内部类,并且构造方法中添加了一些默认的奖品。基本准备工作就是这些,后面写的时候需要添加什么再添加好了。接下来就可以开始拿起画笔愉快的画这个命运之轮了。

根据奖品个数,计算一下扇形扫过的角度,来个 for 循环就可以将每个奖品对应的扇形绘制出来了:

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < mPrizeList.size(); i++) {
            //绘制扇形
            mPaint.setColor(mPrizeList.get(i).getBackgroundColor());
            //计算每个扇形开始的角度,Android 中在绘制扇形时从顺时针 90 度开始绘制,所以起始角度要减 90
            float startAngle = (float) 360 / (float) mPrizeList.size() * i - 90;
            float sweepAngle = (float) 360 / (float) mPrizeList.size();
            canvas.drawArc(mRectF, startAngle, sweepAngle, true, mPaint);
        }
    }

3 绘制文字

接下来需要在扇形中绘制奖品的说明文字,刚开始以为这个很简单,以为找到扇形中的中间位置的坐标直接  drawText() 就行了,但是绘制文字没有改变文字方向的 API,所以不能直接绘制,但是 Canvas 这样一个 API:

public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint)

它可以沿着指定 path 来绘制文字,也就可以改变文字方向了。在最后思考后,我的思路是这样的:

在刚才绘制扇形下面加入绘制文字的代码:

            //处理文字,因为想竖着绘制文字,一个字一个字的话
            String text = mPrizeList.get(i).getText();
            text = new StringBuilder(text).reverse().toString();
            for (int j = 0; j < text.length(); j++) {
                //重置 path,首先获取扇形的弧形部分的路径
                mPath.reset();
                mPath.addArc(mRectF, startAngle, sweepAngle);
                //获取扇形路径的起点
                mPathMeasure.setPath(mPath, false);
                mPathMeasure.getPosTan(0, pos, tan);
                //重置 path,连接圆心和扇形路径的起点
                mPath.reset();
                mPath.moveTo(mWidth / 2, mHeight / 2);
                mPath.lineTo(pos[0], pos[1]);
                //为了好看一点只在扇形的中间部分绘制文字,两头各留 1/4 的空间,获取中间一段的第 j 个等分点的坐标
                mPathMeasure.setPath(mPath, false);
                float distance = (mPathMeasure.getLength() / 2) / (text.length() - 1) * j
                        + mPathMeasure.getLength() / 4;
                mPathMeasure.getPosTan(distance, pos, tan);
                float x1 = pos[0];
                float y1 = pos[1];

                //同上,只是这里连接圆心和扇形路径的中点
                //重置 path,首先获取扇形的弧形部分的路径
                mPath.reset();
                mPath.addArc(mRectF, startAngle, sweepAngle);
                //获取扇形路径的起点
                mPathMeasure.setPath(mPath, false);
                mPathMeasure.getPosTan(mPathMeasure.getLength(), pos, tan);
                //重置 path,连接圆心和扇形路径的起点
                mPath.reset();
                mPath.moveTo(mWidth / 2, mHeight / 2);
                mPath.lineTo(pos[0], pos[1]);
                //为了好看一点只在扇形的中间部分绘制文字,两头各留 1/4 的空间,获取中间一段的第 j 个等分点的坐标
                mPathMeasure.setPath(mPath, false);
                mPathMeasure.getPosTan(distance, pos, tan);
                float x2 = pos[0];
                float y2 = pos[1];

                //重置 path,连接获取的两个第 j 个等分点,作为绘制文字的path
                mPath.reset();
                mPath.moveTo(x1, y1);
                mPath.lineTo(x2, y2);
                //修改文字画笔的颜色,字体大小等属性
                mPathMeasure.setPath(mPath, false);
                //这里 drawPath() 是为了看看文字到底是沿着哪条 path 绘制的,实际运行后要注释掉
                mPaint.setColor(Color.BLACK);
                mPaint.setStrokeWidth(5f);
                mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
                canvas.drawPath(mPath, mPaint);
                //TextSize 会影响下面测量文字整体的方法 getTextBounds(),所以要在 getTextBounds() 方法前调用
                mTextPaint.setTextSize(sp2px(getContext(), 20f));
                mTextPaint.setColor(Color.BLACK);
                mTextPaint.setTypeface(Typeface.DEFAULT);
                mTextPaint.getTextBounds(text, j, j + 1, mTextBounds);
                //沿着 path 绘制文字,并且将文字绘制在路径中间,即居中绘制
                canvas.drawTextOnPath(text.substring(j, j + 1), mPath, mPathMeasure.getLength() / 2 - mTextBounds.width() / 2, 0, mTextPaint);
            }

现在效果是这样:

文字下面的线只是为了看看文字到底是沿着哪条 path 绘制的,实际运行后要注释掉。

4 绘制中心按钮及结果箭头

到现在,轮盘的基本雏形已经有了,但要想知道抽奖结果,还需要一个箭头指示旋转后最后停下来的结果,再在中心加个按钮到时候来触发抽奖事件:

给中间按钮一个默认文字:


    private String centerText = "GO";  //轮盘中心的文字

然后将下列代码添加到刚才绘制扇形的 for 循环后:

        //绘制以轮盘圆心为圆心,以轮盘半径的 1/10 为半径的白色圆
        int radius = mWidth / 10;
        mPaint.setColor(Color.WHITE);
        canvas.drawCircle(mWidth / 2, mHeight / 2, radius, mPaint);

        //绘制以轮盘圆心为圆心,以白色圆半径再减去 5dp 为半径的红色圆
        radius = mWidth / 10 - dp2px(getContext(), 5f);
        mPaint.setColor(Color.RED);
        canvas.drawCircle(mWidth / 2, mHeight / 2, radius, mPaint);

        //在红色圆上绘制一个箭头
        mPath.reset();
        mPaint.setColor(Color.RED);
        mPath.moveTo(mWidth / 2 - (float) (Math.sin(Math.PI / 12) * radius)
                , mHeight / 2 - (float) (Math.cos(Math.PI / 12) * radius));
        mPath.lineTo(mWidth / 2
                , mHeight / 2 - radius * 2f);
        mPath.lineTo(mWidth / 2 + (float) (Math.sin(Math.PI / 12) * radius)
                , mHeight / 2 - (float) (Math.cos(Math.PI / 12) * radius));
        canvas.drawPath(mPath, mPaint);

        //在红色圆中绘制文字,默认为 Go
        mTextPaint.setTextSize(sp2px(getContext(), 40f));
        mTextPaint.setColor(Color.WHITE);
        mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
        mTextPaint.getTextBounds(centerText, 0, centerText.length(), mTextBounds);
        canvas.drawText(centerText, mWidth / 2 - mTextBounds.width() / 2, mHeight / 2 + mTextBounds.height() / 2, mTextPaint);

如果感觉不知道添加到什么地方的话不要方,最后会贴出源码,现在是这样的效果:

5 旋转

至此,这个命运之轮的静态样子已经绘制完成了,最后只需要给它中间的按钮增加一个点击事件,点击后轮盘进行旋转,旋转一段时间或者一定角度后停下来,当然,这个旋转角度还是要随机一下的,不然每次结果都是一样的了。旋转的方法有很多,这里我介绍我的思路:

给一个旋转角度的变量 mRotateDegrees 用以在 onDraw() 方法中旋转画布。在触发抽奖事件时通过 Random 类获取一个在 mPrizeList 元素下标范围内的随机数 ,这个随机数就是最后的抽奖结果。计算出这个抽奖结果所在扇形的开始度数,用 360 一减它就是我们需要旋转的度数,为了效果看起来好一点可以多再加几个 360 让它多旋转几圈。然后开启一个动画,在动画监听中修改 mRotateDegrees 并重绘。

在 onDraw() 方法中绘制扇形前根据 mRotateDegrees 旋转画布,就能实现轮盘旋转的效果。当然轮盘中心的白色圆、开始抽奖的按钮和文字不用旋转,所以在绘制扇形和扇形中的文字前要保存一下画布状态,在绘制扇形和扇形中的文字完成后恢复画布状态。

下面是代码,也是整个源码:

public class WheelOfFortuneView extends View {
    private static final String TAG = "WheelOfFortuneView";
    private int mWidth; //控件宽,为屏幕宽和高的较小值
    private int mHeight;    //控件高,为屏幕宽和高的较小值
    private Paint mPaint;   //画笔
    private TextPaint mTextPaint;   //绘制文字的画笔
    private RectF mRectF;   //扇形绘制区域
    private Path mPath; //路径
    private PathMeasure mPathMeasure;   //路径测量的对象
    private Rect mTextBounds;   //文字绘制区域
    private float[] pos = new float[2]; //记录路径中某个点的坐标数组
    private float[] tan = new float[2];
    private float mRotateDegrees = 0;   //旋转角度
    private GestureDetector mGestureDetector;   //手势监听器,其实也就监听了一个单击事件

    private List<Prize> mPrizeList = new ArrayList<>();
    private String centerText = "GO";  //轮盘中心的文字
    private IOnPrizeDrawListener mOnPrizeDrawListener;

    private GestureDetector.OnGestureListener mOnGestureListener = new GestureDetector.OnGestureListener() {
        @Override
        public boolean onDown(MotionEvent e) {
            //return true 才会响应后续事件,如 onSingleTapUp、onFling 等
            return true;
        }

        @Override
        public void onShowPress(MotionEvent e) {

        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            //单击事件的触发范围在 Go 按钮的范围内才响应抽奖事件
            int goButtonRadius = mWidth / 10 - dp2px(getContext(), 5f);
            if (e.getX() > mWidth / 2 - goButtonRadius
                    && e.getX() < mWidth / 2 + goButtonRadius
                    && e.getY() > mHeight / 2 - goButtonRadius
                    && e.getY() < mHeight / 2 + goButtonRadius) {
                startPrizeDraw();
            }
            return false;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            return false;
        }

        @Override
        public void onLongPress(MotionEvent e) {

        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            return false;
        }
    };

    public WheelOfFortuneView(Context context) {
        this(context, null);
    }

    public WheelOfFortuneView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WheelOfFortuneView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);

        mTextPaint = new TextPaint();
        mTextPaint.setAntiAlias(true);

        mRectF = new RectF();
        mPath = new Path();
        mPathMeasure = new PathMeasure();
        mTextBounds = new Rect();

        mGestureDetector = new GestureDetector(getContext(), mOnGestureListener);
        mPrizeList.add(new Prize("一等奖", Color.RED));
        mPrizeList.add(new Prize("二等奖", Color.YELLOW));
        mPrizeList.add(new Prize("三等奖", Color.BLUE));
        mPrizeList.add(new Prize("谢谢你", Color.GREEN));
        mPrizeList.add(new Prize("一等奖", Color.RED));
        mPrizeList.add(new Prize("二等奖", Color.YELLOW));
        mPrizeList.add(new Prize("三等奖", Color.BLUE));
        mPrizeList.add(new Prize("谢谢你", Color.GREEN));
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = mHeight = Math.min(getContext().getResources().getDisplayMetrics().widthPixels, getContext().getResources().getDisplayMetrics().heightPixels);
        setMeasuredDimension(mWidth, mHeight);

        //绘制扇形的区域
        mRectF.set(0, 0, mWidth, mHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //保存画布状态,在绘制完扇形和文字后恢复
        canvas.save();
        //点击抽奖后开始旋转
        canvas.rotate(mRotateDegrees, (mRectF.right - mRectF.left) / 2, (mRectF.bottom - mRectF.top) / 2);

        for (int i = 0; i < mPrizeList.size(); i++) {
            //绘制扇形
            mPaint.setColor(mPrizeList.get(i).getBackgroundColor());
            //计算每个扇形开始的角度,Android 中在绘制扇形时从顺时针 90 度开始绘制,所以起始角度要减 90
            float startAngle = (float) 360 / (float) mPrizeList.size() * i - 90;
            float sweepAngle = (float) 360 / (float) mPrizeList.size();
            canvas.drawArc(mRectF, startAngle, sweepAngle, true, mPaint);

            //处理文字,因为想竖着绘制文字,一个字一个字的话
            String text = mPrizeList.get(i).getText();
            text = new StringBuilder(text).reverse().toString();
            for (int j = 0; j < text.length(); j++) {
                //重置 path,首先获取扇形的弧形部分的路径
                mPath.reset();
                mPath.addArc(mRectF, startAngle, sweepAngle);
                //获取扇形路径的起点
                mPathMeasure.setPath(mPath, false);
                mPathMeasure.getPosTan(0, pos, tan);
                //重置 path,连接圆心和扇形路径的起点
                mPath.reset();
                mPath.moveTo(mWidth / 2, mHeight / 2);
                mPath.lineTo(pos[0], pos[1]);
                //为了好看一点只在扇形的中间部分绘制文字,两头各留 1/4 的空间,获取中间一段的第 j 个等分点的坐标
                mPathMeasure.setPath(mPath, false);
                float distance = (mPathMeasure.getLength() / 2) / (text.length() - 1) * j
                        + mPathMeasure.getLength() / 4;
                mPathMeasure.getPosTan(distance, pos, tan);
                float x1 = pos[0];
                float y1 = pos[1];

                //同上,只是这里连接圆心和扇形路径的中点
                //重置 path,首先获取扇形的弧形部分的路径
                mPath.reset();
                mPath.addArc(mRectF, startAngle, sweepAngle);
                //获取扇形路径的起点
                mPathMeasure.setPath(mPath, false);
                mPathMeasure.getPosTan(mPathMeasure.getLength(), pos, tan);
                //重置 path,连接圆心和扇形路径的起点
                mPath.reset();
                mPath.moveTo(mWidth / 2, mHeight / 2);
                mPath.lineTo(pos[0], pos[1]);
                //为了好看一点只在扇形的中间部分绘制文字,两头各留 1/4 的空间,获取中间一段的第 j 个等分点的坐标
                mPathMeasure.setPath(mPath, false);
                mPathMeasure.getPosTan(distance, pos, tan);
                float x2 = pos[0];
                float y2 = pos[1];

                //重置 path,连接获取的两个第 j 个等分点,作为绘制文字的path
                mPath.reset();
                mPath.moveTo(x1, y1);
                mPath.lineTo(x2, y2);
                //修改文字画笔的颜色,字体大小等属性
                mPathMeasure.setPath(mPath, false);
                //这里 drawPath() 是为了看看文字到底是沿着哪条 path 绘制的,实际运行后要注释掉
//                mPaint.setColor(Color.BLACK);
//                mPaint.setStrokeWidth(5f);
//                mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
//                canvas.drawPath(mPath, mPaint);
                //TextSize 会影响下面测量文字整体的方法 getTextBounds(),所以要在 getTextBounds() 方法前调用
                mTextPaint.setTextSize(sp2px(getContext(), 20f));
                mTextPaint.setColor(Color.BLACK);
                mTextPaint.setTypeface(Typeface.DEFAULT);
                mTextPaint.getTextBounds(text, j, j + 1, mTextBounds);
                //沿着 path 绘制文字,并且将文字绘制在路径中间,即居中绘制
                canvas.drawTextOnPath(text.substring(j, j + 1), mPath, mPathMeasure.getLength() / 2 - mTextBounds.width() / 2, 0, mTextPaint);
            }
        }
        //轮盘中心的白色圆、开始抽奖的按钮和文字不用旋转,所以在这里恢复画布状态
        canvas.restore();

        //绘制以轮盘圆心为圆心,以轮盘半径的 1/10 为半径的白色圆
        int radius = mWidth / 10;
        mPaint.setColor(Color.WHITE);
        canvas.drawCircle(mWidth / 2, mHeight / 2, radius, mPaint);

        //绘制以轮盘圆心为圆心,以白色圆半径再减去 5dp 为半径的红色圆
        radius = mWidth / 10 - dp2px(getContext(), 5f);
        mPaint.setColor(Color.RED);
        canvas.drawCircle(mWidth / 2, mHeight / 2, radius, mPaint);

        //在红色圆上绘制一个箭头
        mPath.reset();
        mPaint.setColor(Color.RED);
        mPath.moveTo(mWidth / 2 - (float) (Math.sin(Math.PI / 12) * radius)
                , mHeight / 2 - (float) (Math.cos(Math.PI / 12) * radius));
        mPath.lineTo(mWidth / 2
                , mHeight / 2 - radius * 2f);
        mPath.lineTo(mWidth / 2 + (float) (Math.sin(Math.PI / 12) * radius)
                , mHeight / 2 - (float) (Math.cos(Math.PI / 12) * radius));
        canvas.drawPath(mPath, mPaint);

        //在红色圆中绘制文字,默认为 Go
        mTextPaint.setTextSize(sp2px(getContext(), 40f));
        mTextPaint.setColor(Color.WHITE);
        mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
        mTextPaint.getTextBounds(centerText, 0, centerText.length(), mTextBounds);
        canvas.drawText(centerText, mWidth / 2 - mTextBounds.width() / 2, mHeight / 2 + mTextBounds.height() / 2, mTextPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return mGestureDetector.onTouchEvent(event);
    }

    private void startPrizeDraw() {
        //抽奖结果的下标
        final int random = new Random().nextInt(mPrizeList.size() - 1);
        //计算出抽奖结果所在扇形的开始度数
        float endRotateDegrees = 360 - 360 / mPrizeList.size() * random;
        //再减去扇形扫过度数的一半,让其最后旋转到抽奖结果所在扇形的中间
        endRotateDegrees -= 360 / mPrizeList.size() / 2;
        //多旋转几圈
        endRotateDegrees += 360 * 5;
        //以 endRotateDegrees 开始动画,在动画监听中更新 mRotateDegrees 的值并让其重绘
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, endRotateDegrees);
        valueAnimator.setDuration(3 * 1000);
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mRotateDegrees = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        valueAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                mRotateDegrees = 0;
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                Toast.makeText(getContext(), "恭喜你抽中了" + mPrizeList.get(random).getText(), Toast.LENGTH_SHORT).show();
                if (mOnPrizeDrawListener != null) {
                    mOnPrizeDrawListener.onPrizeDrawResult(mPrizeList.get(random));
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        valueAnimator.start();
    }

    private static int dp2px(Context context, float dpValue) {
        float density = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * density + 0.5f);
    }

    private static int sp2px(Context context, float spValue) {
        float scaleDensity = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * scaleDensity + 0.5f);
    }

    /**
     * Description:奖品内部类
     * Date:2019/1/11
     */
    public static class Prize {
        private String text;    //奖品名
        private int backgroundColor;    //对应扇形的背景色

        public Prize() {
        }

        public Prize(String text, int backgroundColor) {
            this.text = text;
            this.backgroundColor = backgroundColor;
        }

        public String getText() {
            return text;
        }


        public int getBackgroundColor() {
            return backgroundColor;
        }
    }

    /**
     * Description:抽奖结果回调接口
     * Date:2019/1/11
     */
    public interface IOnPrizeDrawListener {
        void onPrizeDrawResult(Prize prize);
    }

    public void setPrizeList(List<Prize> prizeList) {
        this.mPrizeList = prizeList;
        invalidate();
    }

    public void setCenterText(String centerText) {
        this.centerText = centerText;
    }

    public void setOnPrizeDrawListener(IOnPrizeDrawListener onPrizeDrawListener) {
        mOnPrizeDrawListener = onPrizeDrawListener;
    }
}

下面是最终效果:

6 总结

手势旋转有点复杂,要考虑的情况太多所以就没有加。从效果上来说这个自定义 View 并不复杂,不过我觉得这次自定义 View 重要的是在绘制文字的时候,刚开始不知道如何能把文字排列得好看一点,在后来换了一个方式思考后一下逻辑就清晰了,所以说思路真的很重要。

今后在选择困难症犯病的时候就用这个轮盘来决定一下结果吧。

猜你喜欢

转载自blog.csdn.net/zgcqflqinhao/article/details/86241916