下列关于网站开发中网页上传和,网页浏览器历史记录恢复,全景网互动平台,淄博网站搭建公司我们要实现的是如下的效果#xff0c;1.该view在设置属性之后时候会有数字和圆圈不断增长的效果2.该view在按下和放开状态下显示不同的样式。这种效果逻辑上并不复杂#xff0c;底层灰色圆圈和蓝色扇形圆圈都是用canvas.drawArc()绘制出来的#xff0c;中间的数字用drawtext…我们要实现的是如下的效果1.该view在设置属性之后时候会有数字和圆圈不断增长的效果2.该view在按下和放开状态下显示不同的样式。这种效果逻辑上并不复杂底层灰色圆圈和蓝色扇形圆圈都是用canvas.drawArc()绘制出来的中间的数字用drawtext绘制数字不断增长的效果用了继承Animation的动画类在按下和放开状态下显示不同的样式是重写了View 的setPressed()方法。先贴出所有代码再一一解释import com.jcodecraeer.util.MyUtils;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.graphics.Rect;import android.graphics.RectF;import android.graphics.Typeface;import android.graphics.Paint.Align;import android.graphics.Paint.Style;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.view.animation.Animation;import android.view.animation.Transformation;public class CircleBar extends View {private RectF mColorWheelRectangle new RectF();private Paint mDefaultWheelPaint;private Paint mColorWheelPaint;private Paint textPaint;private float mColorWheelRadius;private float circleStrokeWidth;private float pressExtraStrokeWidth;private String mText;private int mCount;private float mSweepAnglePer;private float mSweepAngle;private int mTextSize;BarAnimation anim;public CircleBar(Context context) {super(context);init(null, 0);}public CircleBar(Context context, AttributeSet attrs) {super(context, attrs);init(attrs, 0);}public CircleBar(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init(attrs, defStyle);}private void init(AttributeSet attrs, int defStyle) {circleStrokeWidth MyUtils.dip2px(getContext(), 10);pressExtraStrokeWidth MyUtils.dip2px(getContext(), 2);mTextSize MyUtils.dip2px(getContext(), 40);mColorWheelPaint new Paint(Paint.ANTI_ALIAS_FLAG);mColorWheelPaint.setColor(0xFF29a6f6);mColorWheelPaint.setStyle(Paint.Style.STROKE);mColorWheelPaint.setStrokeWidth(circleStrokeWidth);mDefaultWheelPaint new Paint(Paint.ANTI_ALIAS_FLAG);mDefaultWheelPaint.setColor(0xFFeeefef);mDefaultWheelPaint.setStyle(Paint.Style.STROKE);mDefaultWheelPaint.setStrokeWidth(circleStrokeWidth);textPaint new Paint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG);textPaint.setColor(0xFF333333);textPaint.setStyle(Style.FILL_AND_STROKE);textPaint.setTextAlign(Align.LEFT);textPaint.setTextSize(mTextSize);mText 0;mSweepAngle 0;anim new BarAnimation();anim.setDuration(2000);}Overrideprotected void onDraw(Canvas canvas) {canvas.drawArc(mColorWheelRectangle, -90, 360, false, mDefaultWheelPaint);canvas.drawArc(mColorWheelRectangle, -90, mSweepAnglePer, false, mColorWheelPaint);Rect bounds new Rect();String textstrmCount;textPaint.getTextBounds(textstr, 0, textstr.length(), bounds);canvas.drawText(textstr,(mColorWheelRectangle.centerX())- (textPaint.measureText(textstr) / 2),mColorWheelRectangle.centerY() bounds.height() / 2,textPaint);}Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int height getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec);int width getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);int min Math.min(width, height);setMeasuredDimension(min, min);mColorWheelRadius min - circleStrokeWidth -pressExtraStrokeWidth ;mColorWheelRectangle.set(circleStrokeWidthpressExtraStrokeWidth, circleStrokeWidthpressExtraStrokeWidth,mColorWheelRadius, mColorWheelRadius);}Overridepublic void setPressed(boolean pressed) {Log.i(TAG,call setPressed );if (pressed) {mColorWheelPaint.setColor(0xFF165da6);textPaint.setColor(0xFF070707);mColorWheelPaint.setStrokeWidth(circleStrokeWidthpressExtraStrokeWidth);mDefaultWheelPaint.setStrokeWidth(circleStrokeWidthpressExtraStrokeWidth);textPaint.setTextSize(mTextSize-pressExtraStrokeWidth);} else {mColorWheelPaint.setColor(0xFF29a6f6);textPaint.setColor(0xFF333333);mColorWheelPaint.setStrokeWidth(circleStrokeWidth);mDefaultWheelPaint.setStrokeWidth(circleStrokeWidth);textPaint.setTextSize(mTextSize);}super.setPressed(pressed);this.invalidate();}public void startCustomAnimation(){this.startAnimation(anim);}public void setText(String text){mText text;this.startAnimation(anim);}public void setSweepAngle(float sweepAngle){mSweepAngle sweepAngle;}public class BarAnimation extends Animation {/*** Initializes expand collapse animation, has two types, collapse (1) and expand (0).* param view The view to animate* param type The type of animation: 0 will expand from gone and 0 size to visible and layout size defined in xml.* 1 will collapse view and set to gone*/public BarAnimation() {}Overrideprotected void applyTransformation(float interpolatedTime, Transformation t) {super.applyTransformation(interpolatedTime, t);if (interpolatedTime 1.0f) {mSweepAnglePer interpolatedTime * mSweepAngle;mCount (int)(interpolatedTime * Float.parseFloat(mText));} else {mSweepAnglePer mSweepAngle;mCount Integer.parseInt(mText);}postInvalidate();}}}属性变量及其说明private RectF mColorWheelRectangle new RectF();圆圈的矩形范围private Paint mDefaultWheelPaint; 绘制底部灰色圆圈的画笔private Paint mColorWheelPaint; 绘制蓝色扇形的画笔private Paint textPaint; 中间文字的画笔private float mColorWheelRadius; 圆圈普通状态下的半径private float circleStrokeWidth; 圆圈的线条粗细private float pressExtraStrokeWidth;按下状态下增加的圆圈线条增加的粗细private String mText;中间文字内容private int mCount; 为了达到数字增加效果而添加的变量他和mText其实代表一个意思private float mSweepAnglePer; 为了达到蓝色扇形增加效果而添加的变量他和mSweepAngle其实代表一个意思private float mSweepAngle; 扇形弧度private int mTextSize;文字颜色BarAnimation anim;动画类构造方法调用之后第一个调用的是init方法在该方法中初始化了各种画笔的颜色风格等字体大小和线条粗细则使用了我自己定义的工具函数dip2px()这样做的目的是在不同分辨率的手机上相同数值的最终显示效果差别不大比如字体大小mTextSize的初始化mTextSize MyUtils.dip2px(getContext(), 40);还定义了动画对象以及动画持续时间anim new BarAnimation();anim.setDuration(2000);其中BarAnimation为自定义的动画类public class BarAnimation extends Animation {/*** Initializes expand collapse animation, has two types, collapse (1) and expand (0).* param view The view to animate* param type The type of animation: 0 will expand from gone and 0 size to visible and layout size defined in xml.* 1 will collapse view and set to gone*/public BarAnimation() {}Overrideprotected void applyTransformation(float interpolatedTime, Transformation t) {super.applyTransformation(interpolatedTime, t);if (interpolatedTime 1.0f) {mSweepAnglePer interpolatedTime * mSweepAngle;mCount (int)(interpolatedTime * Float.parseFloat(mText));} else {mSweepAnglePer mSweepAngle;mCount Integer.parseInt(mText);}postInvalidate();}}这个动画类利用了applyTransformation参数中的interpolatedTime参数(从0到1)的变化特点实现了该View的某个属性随时间改变而改变。原理是在每次系统调用animation的applyTransformation()方法时改变mSweepAnglePermCount的值然后调用postInvalidate()不停的绘制view。if (interpolatedTime 1.0f) {mSweepAnglePer interpolatedTime * mSweepAngle;mCount (int)(interpolatedTime * Float.parseFloat(mText));}mSweepAnglePermCount这两个属性只是动画过程中要用到的临时属性mText和mSweepAngle才是动画结束之后表示扇形弧度和中间数值的真实值。绘制方法在onDraw方法中我们绘制了圆圈、扇形以及文字但是绘制需要用到的一些坐标值是经过计算得出的比如绘制扇形canvas.drawArc(mColorWheelRectangle, -90, mSweepAnglePer, false, mColorWheelPaint);mColorWheelRectangle是一个矩形这个矩形的上下左右边界都是在onMeasure方法中根据控件所分配的大小得出来的。具体计算方式在onMeasure的实现中Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int height getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec);int width getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);int min Math.min(width, height);setMeasuredDimension(min, min);mColorWheelRadius min - circleStrokeWidth -pressExtraStrokeWidth ;mColorWheelRectangle.set(circleStrokeWidthpressExtraStrokeWidth, circleStrokeWidthpressExtraStrokeWidth,mColorWheelRadius, mColorWheelRadius);}从setMeasuredDimension(min, min)可以看出我们强制该View为正方形。上面说到的mColorWheelRectangle矩形区域比控件的实际边界要小这样做的目的是在按下状态下状态下让圆圈的线条变大之后也并不会超出矩形区域。按下松开view样式改变的实现改变样式很简单只需改变画笔的样式就可以了关键是在什么地方改变。我们都知道设置背景成selector就能是按下松开状态下背景改变但是直接设背景不满足这里的要求因为这是个圆圈如果设置背景那肯定不会紧贴着圆圈边缘但是我们可以在不同状态下更改画笔然后重绘达到相同的效果。如何检测到按下与松开呢看了view的源码知道setPressed()方法可以满足我们的要求Overridepublic void setPressed(boolean pressed) {Log.i(TAG,call setPressed );if (pressed) {mColorWheelPaint.setColor(0xFF165da6);textPaint.setColor(0xFF070707);mColorWheelPaint.setStrokeWidth(circleStrokeWidthpressExtraStrokeWidth);mDefaultWheelPaint.setStrokeWidth(circleStrokeWidthpressExtraStrokeWidth);textPaint.setTextSize(mTextSize-pressExtraStrokeWidth);} else {mColorWheelPaint.setColor(0xFF29a6f6);textPaint.setColor(0xFF333333);mColorWheelPaint.setStrokeWidth(circleStrokeWidth);mDefaultWheelPaint.setStrokeWidth(circleStrokeWidth);textPaint.setTextSize(mTextSize);}super.setPressed(pressed);this.invalidate();}每次按下或者松开setPressed都会被调用我们重写该方法但要注意调用super.setPress()不然长按放开之后boolean pressed参数仍然为true这样松开之后样式就保持按下的状态。具体原因还需要多阅读view的源码。总结其实这里最主要的是要有耐心了解canvas的一些方法还有就是要根据自己的需求有针对性的分析view的源码。