不知不覺已經出來工作了7個月,今天剛剛好轉正一個月了,花了1個多月的時間,在公司完成了android集成RN的項目。做的時候真的遇到好多坑,還好都一一解決了。O(∩_∩)O哈哈~,做完這個項目又閑下來的。好想有項目迭代!!!
效果圖--錄屏軟件錄的有點差
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
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 計算到弧長之后根據的需要修改
繪制轉盤上的圖片
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()繪制的開始點
image.png
canvas.drawArc() 在右邊x軸正方向開始繪制
image.png
指針指向的方向是270度,旋轉方向為順時針,現在這里有10個扇形就是每個占了36°,當旋轉了36°,指針指向的是黃忠。我這里寫以尷尬差點中獎為第0個元素,那么第1個元素就是元歌,如果我想要元歌的英雄旋轉的度數就是369,公式:360/個數×(個數-位置)*
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) {
}
});
}