本文主要是介绍自定义View实战之渐变,可拨动,带动画圆环控件实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
效果图预览
1. 分析
1. 绘制中间数字
2. 绘制带刻度的圆环 考虑分成若干等份
3. 绘制渐变圆环 需要用到渐变相关属性
4. 动画处理的同时需要考虑时时计算角度
5. 圆环开关控制按钮的波动范围处理
2. 实现原理
1. 绘制文字这个简单
2. 绘制刻度圆环 分等份 用canvas.drawArc画若干圆环
3. 绘制渐变圆环,需要用到Paint的setShader方法设置渐变颜色
4. 属性动画处理
3. 初始化一些东西 初始化一般我放在onSizeChanged方法中
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mCenterX = w / 2;mCenterY = h / 2;int[] colors = {Color.RED,Color.GREEN,Color.YELLOW};mSweepGradient = new SweepGradient(mCenterX,mCenterY, colors,null);mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ring_dot);mBitmap = conversionBitmap(mBitmap,dp2px(30),dp2px(30));mMinValidateTouchArcRadius = (int) (mCircleRadius - mBitmap.getWidth() / 2 * 1.5);mMaxValidateTouchArcRadius = (int) mCircleRadius;
}
4. 绘制中间数字和带刻度线的圆环
/*** 画带刻度线的圆环*/
private void drawScaleRing(Canvas canvas) {float margin = mRingRadius - dp20;float left = mCenterX - margin;float top = mCenterY - margin;float right = left + 2 * margin;float bottom = top + 2 * margin;mScaleReacF.set(left,top,right,bottom);// 等分成360 / 6 = 60份 保证间距一样的for (int i = 0; i < sweepAngle / 6; i++) {canvas.drawArc(mScaleReacF, startAngle + i * 6, 1f, false, mScaleRingPaint);}
}/*** 画中间的数字*/
private void drawMidNum(Canvas canvas) {String value = String.valueOf(mStepNum);//测量文字的宽高mTextPaint.getTextBounds(value, 0, value.length(), mTextRect);int width = mTextRect.width();//文字宽int height = mTextRect.height();//文字高canvas.drawText(value, mCenterX - width / 2, mCenterY + height / 2, mTextPaint);
}
5. 绘制带渐变色的进度圆环
/*** 画进度圆环*/
private void drawRingProgress(Canvas canvas) {canvas.save();//canvas.rotate(-90);float left = mCenterX - mRingRadius;float top = mCenterY - mRingRadius;float right = left + 2 * mRingRadius;float bottom = top + 2 * mRingRadius;mProgressReacF.set(left,top,right,bottom);//设置渐变颜色mProgressPaint.setShader(mSweepGradient);float sweepAngle = mCurrentAngle;//绘制圆环 startAngle开始角度 sweepAngle扫瞄的角度canvas.drawArc(mProgressReacF, startAngle, sweepAngle, false, mProgressPaint);canvas.restore();
}
6. 进度条动画和数字处理
//加载进度条动画
public void setProgressAnimation(float last, float currentProgress, long duration) {mCurrentAngle = (currentProgress / mMaxProgress) * sweepAngle;ValueAnimator progressAnimator = ValueAnimator.ofFloat(last, mCurrentAngle);progressAnimator.setDuration(duration);progressAnimator.setTarget(mCurrentAngle);progressAnimator.setInterpolator(new AccelerateInterpolator());progressAnimator.start();progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {/**每次要绘制的圆弧角度**/mCurrentAngle = (float) animation.getAnimatedValue();//根据当前进度和总进度计算当前步数mStepNum = (int) (mCurrentAngle / sweepAngle * mMaxStepNum);postInvalidate();}});
}
7. 触摸事件处理
@Override
public boolean onTouchEvent(MotionEvent event) {int x = (int) event.getX();int y = (int) event.getY();if (mIsShowControlIcon && (event.getAction() == MotionEvent.ACTION_MOVE || isTouchArc(x, y))) {// 通过当前触摸点搞到cos角度值float cos = computeCos(x, y);// 通过反三角函数获得角度值double angle;if (x < mCenterX) { // 滑动超过180度angle = Math.PI * RADIAN + Math.acos(cos) * RADIAN;} else { // 没有超过180度angle = Math.PI * RADIAN - Math.acos(cos) * RADIAN;}if (mCurrentAngle > 270 && angle < 90) {mCurrentAngle = 360;cos = -1;} else if (mCurrentAngle < 90 && angle > 270) {mCurrentAngle = 0;cos = -1;} else {mCurrentAngle = (float) angle;}mCurrentProgress = getSelectedValue();invalidate();return true;} else {return super.onTouchEvent(event);}
}private int getSelectedValue() {return Math.round(mMaxProgress * (mCurrentAngle / sweepAngle));
}/*** 按下时判断按下的点是否按在圆边范围内* @param x* @param y*/
private boolean isTouchArc(int x, int y) {double d = getTouchRadius(x, y);return d >= mMinValidateTouchArcRadius && d <= mMaxValidateTouchArcRadius;
}/*** 计算某点到圆点的距离* @param x* @param y*/
private double getTouchRadius(int x, int y) {int cx = x - mCenterX;int cy = y - mCenterY;return Math.hypot(cx, cy);
}/*** 拿到倾斜的cos值*/
private float computeCos(float x, float y) {float width = x - mCenterX;float height = y - mCenterY;float slope = (float) Math.sqrt(width * width + height * height);return height / slope;
}
7. 项目源代码下载
后面统一提供源代码下载链接
8. 联系方式
QQ:1509815887
这篇关于自定义View实战之渐变,可拨动,带动画圆环控件实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!