android自定義view--抽獎轉(zhuǎn)盤 指定中獎位置

不知不覺已經(jīng)出來工作了7個月,今天剛剛好轉(zhuǎn)正一個月了,花了1個多月的時間,在公司完成了android集成RN的項目。做的時候真的遇到好多坑,還好都一一解決了。O(∩_∩)O哈哈~,做完這個項目又閑下來的。好想有項目迭代?。。?/p>

效果圖--錄屏軟件錄的有點差

test2.gif

實現(xiàn)步驟---思路

  • 設(shè)置轉(zhuǎn)盤的寬高
  • 繪制圓形背景
  • 繪制轉(zhuǎn)盤
  • 繪制轉(zhuǎn)盤上的文字和圖片
  • 轉(zhuǎn)盤的旋轉(zhuǎn)動畫以及監(jiān)聽
  • 指定旋轉(zhuǎn)的位置

在onMeasure上設(shè)置轉(zhuǎn)盤的寬高---我在布局中設(shè)置了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;

        //設(shè)置框高都一樣
        setMeasuredDimension(width, width);
    }

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

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

繪制轉(zhuǎn)盤

       //設(shè)置扇形繪制的范圍
        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;
        }

看看效果了---背景原的半徑比轉(zhuǎn)盤的半徑多了paddingleft()/2

image.png

繪制轉(zhuǎn)盤上的文字需要使用到的方法
path.addArc--------添加圓弧路徑
canvas.drawTextOnPath------根據(jù)路徑繪制文字

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

            //根據(jù)路徑繪制文字
            canvas.drawTextOnPath(startText, path, hOffset, mRadius / 6, mTextPaint);
            canvas.drawTextOnPath(endText, path, endHOffset, mRadius / 6 - h, mTextPaint);
        } else {
            //根據(jù)路徑繪制文字
            canvas.drawTextOnPath(mString, path, hOffset, mRadius / 6, mTextPaint);
        }
    }

弧長公式 length=圓心角度數(shù)xMath.PIx半徑/180 計算到弧長之后根據(jù)的需要修改

繪制轉(zhuǎn)盤上的圖片

image.png

求出x,y的坐標(biāo) 利用三角函數(shù)
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);
        //計算中心點的坐標(biāo)
        int r = mRadius / 2;
        float x = (float) (mCenter + r * Math.cos(angle));
        float y = (float) (mCenter + r * Math.sin(angle));
        //設(shè)置繪制圖片的范圍
        RectF rectF = new RectF(x - imageWidth, y - imageWidth, x + imageWidth, y + imageWidth);
        canvas.drawBitmap(mBitmap, null, rectF, null);
    }

轉(zhuǎn)盤的旋轉(zhuǎn)動畫監(jiān)聽以及指定旋轉(zhuǎn)的位置

先看個圖片canvas.drawArc()繪制的開始點


image.png

canvas.drawArc() 在右邊x軸正方向開始繪制

image.png

指針指向的方向是270度,旋轉(zhuǎn)方向為順時針,現(xiàn)在這里有10個扇形就是每個占了36°,當(dāng)旋轉(zhuǎn)了36°,指針指向的是黃忠。我這里寫以尷尬差點中獎為第0個元素,那么第1個元素就是元歌,如果我想要元歌的英雄旋轉(zhuǎn)的度數(shù)就是369,公式:360/個數(shù)×(個數(shù)-位置)*

image.png

怎么獲取到旋轉(zhuǎn)的信息呢?
使用: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) {

            }
        });
    }

源碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容