android自定义view--抽奖转盘 指定中奖位置

不知不觉已经出来工作了7个月,今天刚刚好转正一个月了,花了1个多月的时间,在公司完成了android集成RN的项目。做的时候真的遇到好多坑,还好都一一解决了。O(∩_∩)O哈哈~,做完这个项目又闲下来的。好想有项目迭代!!!

效果图--录屏软件录的有点差

android自定义view--抽奖转盘 指定中奖位置_第1张图片
test2.gif

实现步骤---思路

  • 设置转盘的宽高
  • 绘制圆形背景
  • 绘制转盘
  • 绘制转盘上的文字和图片
  • 转盘的旋转动画以及监听
  • 指定旋转的位置

在onMeasure上设置转盘的宽高---我在布局中设置了padding=30dp

   @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int w = MeasureSpec.getSize(widthMeasureSpec);
        int h = MeasureSpec.getSize(heightMeasureSpec);

        int width = Math.min(w, h);
        //圆心点
        mCenter = width / 2;
        //半径
        mRadius = (width - getPaddingLeft() * 2) / 2;

        //设置框高都一样
        setMeasuredDimension(width, width);
    }

绘制圆形背景--- canvas.drawCircle(cx,cy,radius,paint);

        canvas.drawCircle(mCenter, mCenter, mCenter - getPaddingLeft() / 2, mBgPaint);

绘制转盘

       //设置扇形绘制的范围
        sectorRectF = new RectF(getPaddingLeft(), getPaddingLeft(),
                mCenter * 2 - getPaddingLeft(), mCenter * 2 - getPaddingLeft());
    for (int i = 0; i < mCount; i++) {
            //扇形的颜色
            mArcPaint.setColor(sectorColor[i % 2]);
            //sectorRectF 扇形绘制范围  startAngle 弧开始绘制角度       
            //sweepAngle 每次绘制弧的角度 
            // useCenter 是否连接圆心 
            canvas.drawArc(sectorRectF, startAngle, sweepAngle, true, mArcPaint);
            startAngle += sweepAngle;
        }

看看效果了---背景原的半径比转盘的半径多了paddingleft()/2

android自定义view--抽奖转盘 指定中奖位置_第2张图片
image.png

绘制转盘上的文字需要使用到的方法
path.addArc--------添加圆弧路径
canvas.drawTextOnPath------根据路径绘制文字

 private void drawTexts(Canvas canvas, String mString) {
        Path path = new Path();
        //添加一个圆弧的路径
        path.addArc(sectorRectF, startAngle, sweepAngle);
        String startText = null;
        String endText = null;
        //测量文字的宽度
        float textWidth = mTextPaint.measureText(mString);
        //水平偏移
        int hOffset = (int) (mRadius * 2 * Math.PI / mCount / 2 - textWidth / 2);
        //计算弧长 处理文字过长换行
        int l = (int) ((360 / mCount) * Math.PI * mRadius / 180);
        if (textWidth > l * 4 / 5) {
            int index = mString.length() / 2;
            startText = mString.substring(0, index);
            endText = mString.substring(index, mString.length());

            float startTextWidth = mTextPaint.measureText(startText);
            float endTextWidth = mTextPaint.measureText(endText);
            //水平偏移
            hOffset = (int) (mRadius * 2 * Math.PI / mCount / 2 - startTextWidth / 2);
            int endHOffset = (int) (mRadius * 2 * Math.PI / mCount / 2 - endTextWidth / 2);
            //文字高度
            int h = (int) ((mTextPaint.ascent() + mTextPaint.descent()) * 1.5);

            //根据路径绘制文字
            canvas.drawTextOnPath(startText, path, hOffset, mRadius / 6, mTextPaint);
            canvas.drawTextOnPath(endText, path, endHOffset, mRadius / 6 - h, mTextPaint);
        } else {
            //根据路径绘制文字
            canvas.drawTextOnPath(mString, path, hOffset, mRadius / 6, mTextPaint);
        }
    }

弧长公式 length=圆心角度数xMath.PIx半径/180 计算到弧长之后根据的需要修改

绘制转盘上的图片

android自定义view--抽奖转盘 指定中奖位置_第3张图片
image.png

求出x,y的坐标 利用三角函数
y=sin(角度)×raduis/2+mCenter
x=cos(角度)×raduis/2+mCenter

private void drawIcons(Canvas canvas, Bitmap mBitmap) {
        int imageWidth = mRadius / 10;
        //计算半边扇形的角度 度=Math.PI/180 弧度=180/Math.PI
        float angle = (float) ((startAngle + sweepAngle / 2) * Math.PI / 180);
        //计算中心点的坐标
        int r = mRadius / 2;
        float x = (float) (mCenter + r * Math.cos(angle));
        float y = (float) (mCenter + r * Math.sin(angle));
        //设置绘制图片的范围
        RectF rectF = new RectF(x - imageWidth, y - imageWidth, x + imageWidth, y + imageWidth);
        canvas.drawBitmap(mBitmap, null, rectF, null);
    }

转盘的旋转动画监听以及指定旋转的位置

先看个图片canvas.drawArc()绘制的开始点


android自定义view--抽奖转盘 指定中奖位置_第4张图片
image.png

canvas.drawArc() 在右边x轴正方向开始绘制

android自定义view--抽奖转盘 指定中奖位置_第5张图片
image.png

指针指向的方向是270度,旋转方向为顺时针,现在这里有10个扇形就是每个占了36°,当旋转了36°,指针指向的是黄忠。我这里写以尴尬差点中奖为第0个元素,那么第1个元素就是元歌,如果我想要元歌的英雄旋转的度数就是369,公式:360/个数×(个数-位置)*

android自定义view--抽奖转盘 指定中奖位置_第6张图片
image.png

怎么获取到旋转的信息呢?
使用:Arrays.binarySearch()

 public void rotate(final int i) {

        rotateToPosition = 360 / mCount * (mCount - i);
        float toDegree = 360f * 5 + rotateToPosition;

        animator = ObjectAnimator.ofFloat(PieView.this, "rotation", 0, toDegree);
        animator.setDuration(5000);
        animator.setRepeatCount(0);
        animator.setInterpolator(new DecelerateInterpolator());
        animator.setAutoCancel(true);
        animator.start();

        animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                //指针指向的方向为270度
                if (listener != null) {
                    rotateToPosition = 270 - rotateToPosition;
                    if (rotateToPosition < 0) {
                        rotateToPosition += 360;
                    } else if (rotateToPosition == 0) {
                        rotateToPosition = 270;
                    }
                    position = -Arrays.binarySearch(angles, rotateToPosition) - 1;
                    listener.value(mStrings[position - 1]);
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {


            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
    }

源码

你可能感兴趣的:(android自定义view--抽奖转盘 指定中奖位置)