弧线展示图
如下图所示就是这次的弧线展示图:
根据书中的代码增加了可自定义弧形的大小,并且可以在布局中自定义各部分的颜色和大小设置。
接下来开始介绍如何创建一个这样的自定义View。
很明显,这个自定义View其实分为三个部分,分别是中间的圆形、中间显示的文字和外圈的弧线。有了这样的思路,只要在onDraw()方法中一个个去绘制就可以了。
首先,在初始化的时候,设置好绘制三种图形的参数。圆的代码如下所示:
// 中心圆的圆心坐标
mCircleXY = length/2;
// 中心圆的半径
mRadius = (float) (length*0.5/2);
绘制弧线,需要指定其椭圆的外接矩形,代码如下所示:
// 绘制弧形的外接矩形属性
mArcRectF = new RectF(
(float) (length * 0.1),
(float) (length * 0.1),
(float) (length * 0.9),
(float) (length * 0.9)
);
绘制文字,只要设置好文字的起始绘制位置就可以了。
接下来,我们就可以在onDraw()方法中进行绘制了,代码如下所示:
// 绘制中心圆
canvas.drawCircle(mCircleXY, mCircleXY, mRadius, mCirclePaint);
// 绘制弧形
canvas.drawArc(mArcRectF, 270, mSweepValue, false, mArcPaint);
// 绘制文字
// 测量字体宽度,根据字体的宽度设置在圆环中间
float textWidth = mTextPaint.measureText(mShowText);
// 通过文字的大小和长度将文字绘制在圆的正中心
canvas.drawText(mShowText, 0,mShowText.length(), mCircleXY-(textWidth/2), mCircleXY+(mShowTextSize/4), mTextPaint);
当然,如果想在布局时给这个简单的View自定义属性的话,可以通过attrs.xml文件给这个控件添加可以自定义的属性,attrs.xml中设置的属性可以根据需要添加,在java中的调用方法如下所示:
// 将所有的attrs中的所有样式都存储到TypeArray中
TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.ArcDisplay);
// 给中心圆设置属性
mCirclePaint = new Paint();
mCirclePaint.setColor(ta.getColor(R.styleable.ArcDisplay_centerCircleColor,
ContextCompat.getColor(context,R.color.defCircleColor)));
// 给弧形设置属性
mArcPaint = new Paint();
mArcPaint.setColor(ta.getColor(R.styleable.ArcDisplay_arcColor,
ContextCompat.getColor(context,R.color.defArcColor)));
mArcPaint.setStrokeWidth(ta.getInteger(R.styleable.ArcDisplay_arcWidth, 60));
mArcPaint.setStyle(Paint.Style.STROKE);
setProgress(ta.getFloat(R.styleable.ArcDisplay_arcAngle, 10));
// 给中间文字设置属性
mTextPaint = new Paint();
mTextPaint.setColor(ta.getColor(R.styleable.ArcDisplay_centerTextColor,
ContextCompat.getColor(context,R.color.defTextColor)));
mShowTextSize = ta.getInteger(R.styleable.ArcDisplay_centerFontSize, 10);
mTextPaint.setTextSize(mShowTextSize);
ta.recycle();
当调用者不具体指定属性时,可以给它们都设置一个默认值。
设置完自定义属性后,开始设置如何通过百分比的形式让弧形显示准确的比例长度,代码如下所示:
/**
* 给弧形设置一个角度(百分比的形式)
* @param mSweepValue 角度比例
*/
public void setProgress(float mSweepValue){
if (mSweepValue != 0) {
this.mSweepValue = (float) (360.0 * (mSweepValue / 100.0));
mShowText = mSweepValue + "%";
} else {
this.mSweepValue = 25;
mShowText = 25 + "%";
}
invalidate();
}
通过以上方法就可以实现输入具体的百分比让弧形长度准确显示。
以上就是弧形展示图的实现步骤,有没有很简单。
代码
以下是完整代码:
package com.example.customarc;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
import com.example.arcdisplay.R;
/**
* 自定义弧线展示图
* Created by shize on 2016/8/30.
*/
public class ArcDisplay extends View {
// 中心圆的xy轴坐标
private float mCircleXY;
// 中心圆的半径
private float mRadius;
// 中心圆的画笔
private Paint mCirclePaint;
// 弧线椭圆的画笔
private Paint mArcPaint;
// 弧线扫过的角度
private float mSweepValue;
// 中心圆的文字
private String mShowText;
// 文字的画笔
private Paint mTextPaint;
// 画布的宽
private int length;
// 文字大小尺寸
private int mShowTextSize;
public ArcDisplay(Context context) {
super(context);
}
public ArcDisplay(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context, attrs);
}
public ArcDisplay(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context, attrs);
}
public void initView(Context context, AttributeSet attrs){
// 将所有的attrs中的所有样式都存储到TypeArray中
TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.ArcDisplay);
// 给中心圆设置属性
mCirclePaint = new Paint();
mCirclePaint.setColor(ta.getColor(R.styleable.ArcDisplay_centerCircleColor,
ContextCompat.getColor(context,R.color.defCircleColor)));
// 给弧形设置属性
mArcPaint = new Paint();
mArcPaint.setColor(ta.getColor(R.styleable.ArcDisplay_arcColor,
ContextCompat.getColor(context,R.color.defArcColor)));
mArcPaint.setStrokeWidth(ta.getInteger(R.styleable.ArcDisplay_arcWidth, 60));
mArcPaint.setStyle(Paint.Style.STROKE);
setProgress(ta.getFloat(R.styleable.ArcDisplay_arcAngle, 10));
// 给中间文字设置属性
mTextPaint = new Paint();
mTextPaint.setColor(ta.getColor(R.styleable.ArcDisplay_centerTextColor,
ContextCompat.getColor(context,R.color.defTextColor)));
mShowTextSize = ta.getInteger(R.styleable.ArcDisplay_centerFontSize, 10);
mTextPaint.setTextSize(mShowTextSize);
ta.recycle();
}
@Override
protected void onSizeChanged(int w,int h,int oldW,int oldH){
super.onSizeChanged(w,h,oldW,oldH);
length = w;
mCircleXY = length/2;
mRadius = (float) (length*0.5/2);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 弧线椭圆的外接矩形
RectF mArcRectF;
// 绘制弧形的外接矩形属性
mArcRectF = new RectF(
(float) (length * 0.1),
(float) (length * 0.1),
(float) (length * 0.9),
(float) (length * 0.9)
);
// 绘制中心圆
canvas.drawCircle(mCircleXY, mCircleXY, mRadius, mCirclePaint);
// 绘制弧形
canvas.drawArc(mArcRectF, 270, mSweepValue, false, mArcPaint);
// 绘制文字
// 测量字体宽度,根据字体的宽度设置在圆环中间
float textWidth = mTextPaint.measureText(mShowText);
// 通过文字的大小和长度将文字绘制在圆的正中心
canvas.drawText(mShowText, 0,mShowText.length(), mCircleXY-(textWidth/2), mCircleXY+(mShowTextSize/4), mTextPaint);
}
/**
* 给弧形设置一个角度(百分比的形式)
* @param mSweepValue 角度比例
*/
public void setProgress(float mSweepValue){
if (mSweepValue != 0) {
this.mSweepValue = (float) (360.0 * (mSweepValue / 100.0));
mShowText = mSweepValue + "%";
} else {
this.mSweepValue = 25;
mShowText = 25 + "%";
}
invalidate();
}
}
布局文件调用代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.arcdisplay.MainActivity">
<com.example.customarc.ArcDisplay
android:id="@+id/arc"
android:layout_width="match_parent"
android:layout_height="400dp"
custom:arcAngle="60"
custom:arcColor="#00ff00"
custom:arcWidth="60"
custom:centerCircleColor="#00ff00"
custom:centerFontSize="70"
custom:centerTextColor="#f33" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/txt_angle"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/angle"
android:inputType="numberDecimal"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnYes"
android:text="@string/btn_txt_yes"/>
</LinearLayout>
以下是attrs.xml的代码:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ArcDisplay">
<attr name="centerFontSize" format="integer" />
<attr name="centerTextColor" format="color" />
<attr name="centerCircleColor" format="color" />
<attr name="arcColor" format="color" />
<attr name="arcAngle" format="float" />
<attr name="arcWidth" format="integer" />
</declare-styleable>
</resources>
感谢阅读,下次再见。