自定义View
- 画一个实心圆
- 效果图
- 创建attrs.xml文件
- 初始化样式属性
- 支持Padding属性
- 支持wrap_content属性
- 布局文件中的应用
- 画一个带外圆环的圆
- 效果图
- 创建attrs.xml文件
- 初始化样式属性
- 内圆与外圆环的绘制
- 布局文件中的应用
- 画一个外圆环可根据数值变动的圆
- 效果图
- 创建attrs.xml文件
- 初始化样式属性
- 绘制View
- 提供方法修改样式
- 布局文件中的应用
画一个实心圆
效果图
创建attrs.xml文件
在value文件夹下创建一个名为attrs.xml文件,为圆设置一个背景颜色的属性,代码如下:
<declare-styleable name="CircleView_Solid">
<attr name="CircleColor_Solid" format="color"/>
</declare-styleable>
初始化样式属性
为圆设置颜色属性,并设置抗锯齿
private void InitAttrs(Context context , AttributeSet attrs){
TypedArray array = context.getTheme().obtainStyledAttributes( attrs,R.styleable.CircleView_Solid,0,0 );
mCircleBGColor = array.getColor( R.styleable.CircleView_Solid_CircleColor_Solid,0xFFFFFFFF );
}
private void InitVar(){
mCirclePaint = new Paint( );
mCirclePaint.setAntiAlias( true );
mCirclePaint.setColor( mCircleBGColor );
}
支持Padding属性
由于直接继承view,不再onDraw()中进行处理,是无法直接使用Padding属性,代码如下:
protected void onDraw(Canvas canvas) {
super.onDraw( canvas );
int PaddingLeft = getPaddingLeft();
int PaddingRight = getPaddingRight();
int PaddingTop = getPaddingTop();
int PaddingBottom = getPaddingBottom();
int Width = (getWidth() - (PaddingLeft+PaddingRight)) / 2 +PaddingLeft;
int Height = (getHeight() -(PaddingTop+PaddingBottom))/2+PaddingTop;
int Radius = Math.min( Width,Height )/2;
canvas.drawCircle( Width,Height,Radius,mCirclePaint );
}
支持wrap_content属性
若不在onMeasure()对wrap_content进行处理,效果很可能达不到预期效果,如果控件使用wrap_content属性,那么他的Measure specification mode就为At_Most,而它的宽高就等于specSize,这种情况下specSize是就相当于父容器当前剩余的大小,代码如下:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure( widthMeasureSpec, heightMeasureSpec );
int Width = 500;
int Height = 500;
int WidthMode = MeasureSpec.getMode( widthMeasureSpec );
int WidthSize = MeasureSpec.getSize( widthMeasureSpec );
int HeightMode = MeasureSpec.getMode( heightMeasureSpec );
int HeightSize = MeasureSpec.getSize( heightMeasureSpec );
if (WidthMode == MeasureSpec.AT_MOST && HeightMode == MeasureSpec.AT_MOST){
setMeasuredDimension( Math.min( Width,HeightSize ),Math.min( Height ,HeightSize) );
} else if (WidthMode == MeasureSpec.AT_MOST) {
setMeasuredDimension( Math.min( Width,HeightSize ),HeightSize );
}else if (HeightMode == MeasureSpec.AT_MOST){
setMeasuredDimension( WidthSize,Math.min( Height ,HeightSize) );
}
}
布局文件中的应用
<com.franzliszt.customcircleview.CircleView_Solid
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:CircleColor_Solid="@color/colorRed"
android:padding="10dp"/>
画一个带外圆环的圆
效果图
创建attrs.xml文件
<declare-styleable name="CircleView_Text">
<!-- 内圆颜色-->
<attr name="CircleColor" format="color"/>
<!-- 外圆环颜色-->
<attr name="RingColor" format="color"/>
<!-- 圆的半径-->
<attr name="Radius" format="dimension"/>
<!-- 外圆环的宽度-->
<attr name="StrokeWidth" format="dimension"/>
</declare-styleable>
初始化样式属性
private void InitAttrs(Context context , AttributeSet attrs){
TypedArray array = context.getTheme().obtainStyledAttributes( attrs,R.styleable.CircleView_Text,0,0 );
CircleColor = array.getColor( R.styleable.CircleView_Text_CircleColor,0xFFFFFFFF );
RingColor = array.getColor( R.styleable.CircleView_Text_RingColor,0xFFFFFFFF );
mRadius = array.getDimension( R.styleable.CircleView_Text_Radius,80 );
mStrokeWidth = array.getDimension( R.styleable.CircleView_Text_StrokeWidth,10 );
mRingRadius = mRadius + mStrokeWidth / 2;
}
private void InitVar(){
//内圆
//设置颜色
CirclePaint.setColor( CircleColor );
//设置填充方式
CirclePaint.setStyle( Paint.Style.FILL );
//设置抗锯齿
CirclePaint.setAntiAlias( true );
//外圆环
RingPaint.setColor( RingColor );
RingPaint.setStyle( Paint.Style.STROKE );
RingPaint.setAntiAlias( true );
RingPaint.setStrokeWidth( mStrokeWidth );
}
内圆与外圆环的绘制
protected void onDraw(Canvas canvas) {
super.onDraw( canvas );
mCenterX = getWidth()/2;
mCenterY = getHeight()/2;
canvas.drawCircle( mCenterX,mCenterY,mRadius,CirclePaint );
RectF rect = new RectF( );
rect.left = mCenterX - mRingRadius;
rect.right = 2 * mRingRadius + (mCenterX - mRingRadius);
rect.top = mCenterY - mRingRadius;
rect.bottom = 2 * mRingRadius + (mCenterY - mRingRadius);
canvas.drawArc( rect,0,360,false,RingPaint );
}
布局文件中的应用
<com.franzliszt.customcircleview.CircleView
android:layout_width="100dp"
android:layout_height="100dp"
app:Radius="40dp"
app:StrokeWidth="10dp"
app:CircleColor="@color/colorBlack"
app:RingColor="@color/colorRed"/>
画一个外圆环可根据数值变动的圆
效果图
创建attrs.xml文件
<declare-styleable name="CircleView_Progress">
<!-- 内圆颜色-->
<attr name="CircleProgressColor" format="color"/>
<!-- 外圆环颜色-->
<attr name="RingProgressColor" format="color"/>
<!-- 外圆环覆盖部分颜色-->
<attr name="RingBgProgressColor" format="color"/>
<!-- 文字颜色-->
<attr name="TextProgressColor" format="color"/>
<!-- 圆的半径-->
<attr name="RadiusProgress" format="dimension"/>
<!-- 外圆环的宽度-->
<attr name="StrokeWidthProgress" format="dimension"/>
<attr name="CurrentProgress" format="float"/>
</declare-styleable>
初始化样式属性
private void InitAttrs(Context context , AttributeSet attrs){
TypedArray array = context.getTheme().obtainStyledAttributes( attrs,R.styleable.CircleView_Progress,0,0 );
CircleColor = array.getColor( R.styleable.CircleView_Progress_CircleProgressColor,0xFFFFFFFF );
RingColor = array.getColor( R.styleable.CircleView_Progress_RingProgressColor,0xFFFFFFFF );
RingBgColor = array.getColor( R.styleable.CircleView_Progress_RingBgProgressColor,0xFFFFFFFF );
TextColor = array.getColor( R.styleable.CircleView_Progress_TextProgressColor, 0xFFFFFFFF);
mRadius = array.getDimension( R.styleable.CircleView_Progress_RadiusProgress,80 );
mStrokeWidth = array.getDimension( R.styleable.CircleView_Progress_StrokeWidthProgress,10 );
mCurrentProgress = array.getFloat( R.styleable.CircleView_Progress_CurrentProgress,10 );
mRingRadius = mRadius + mStrokeWidth / 2;
}
private void InitVar(){
//内圆
//设置颜色
CirclePaint.setColor( CircleColor );
//设置填充方式
CirclePaint.setStyle( Paint.Style.FILL );
//设置抗锯齿
CirclePaint.setAntiAlias( true );
//外圆环
RingPaint.setColor( RingColor );
RingPaint.setStyle( Paint.Style.STROKE );
RingPaint.setAntiAlias( true );
RingPaint.setStrokeWidth( mStrokeWidth );
//外圆环覆盖部分
RingBgPaint.setColor( RingBgColor );
RingBgPaint.setStyle( Paint.Style.STROKE );
RingBgPaint.setAntiAlias( true );
RingBgPaint.setStrokeWidth( mStrokeWidth );
//中间文字
TextPaint.setStyle( Paint.Style.FILL );
TextPaint.setAntiAlias( true );
TextPaint.setColor( TextColor );
TextPaint.setTextSize( mRadius/2 );
//文字的高度
Paint.FontMetrics fontMetrics = TextPaint.getFontMetrics();
mTextHeight = (int)Math.ceil( fontMetrics.descent - fontMetrics.ascent );
}
绘制View
protected void onDraw(Canvas canvas) {
super.onDraw( canvas );
mCenterX = getWidth()/2;
mCenterY = getHeight()/2;
canvas.drawCircle( mCenterX,mCenterY,mRadius,CirclePaint );
RectF rect = new RectF( );
rect.left = mCenterX - mRingRadius;
rect.right = 2 * mRingRadius + (mCenterX - mRingRadius);
rect.top = mCenterY - mRingRadius;
rect.bottom = 2 * mRingRadius + (mCenterY - mRingRadius);
canvas.drawArc( rect,0,360,false,RingPaint );
//当mCurrentProgress大于0时,外圆环覆盖部分显示
if (mCurrentProgress > 0){
RectF rect_progress = new RectF( );
rect_progress.left = mCenterX - mRingRadius;
rect_progress.right = 2 * mRingRadius + (mCenterX - mRingRadius);
rect_progress.top = mCenterY - mRingRadius;
rect_progress.bottom = 2 * mRingRadius + (mCenterY - mRingRadius);
//例如外圆环数值为35,即35/100*360,获得外圆环覆盖部分
canvas.drawArc( rect,-90,(float) (mCurrentProgress / mTotalProgress)*360,false,RingBgPaint );
}
//文字部分
String text = mCurrentProgress+"%";
//文字部分的宽度
mTextWidth = TextPaint.measureText( text,0,text.length() );
canvas.drawText( text,mCenterX - mTextWidth / 2, mCenterY + mTextHeight / 4,TextPaint );
}
提供方法修改样式
public void setProgress(double progress){
mCurrentProgress = progress;
postInvalidate();
}
public void setRingBgColor(int Color){
RingBgColor = Color;
postInvalidate();
}
public void setTextColor(int Color){
TextColor = Color;
postInvalidate();
}
布局文件中的应用
<com.franzliszt.customcircleview.CircleView_ProgressBar
android:id="@+id/Progress"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginTop="50dp"
app:Radius="100dp"
app:StrokeWidth="10dp"
app:CircleColor="@color/colorWhite"
app:RingColor="@color/colorGrey"
app:RingProgressColor="@color/colorRed"
app:TextProgressColor="@color/colorPrimary"
app:CurrentProgress="59"
/>