一、项目结构
├─app
│ ├─libs
│ └─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─sky
│ │ │ └─customviewforcircle
│ │ │ ├─activity
│ │ │ ├─utils
│ │ │ ├─viewmodel
│ │ │ └─widget
│ │ └─res
│ │ ├─drawable
│ │ ├─drawable-v24
│ │ ├─drawable-xxhdpi
│ │ ├─layout
│ │ ├─mipmap-anydpi-v26
│ │ ├─mipmap-hdpi
│ │ ├─mipmap-mdpi
│ │ ├─mipmap-xhdpi
│ │ ├─mipmap-xxhdpi
│ │ ├─mipmap-xxxhdpi
│ │ └─values
│ └─test
│ └─java
│ └─com
│ └─sky
│ └─customviewforcircle
└─gradle
└─wrapper
二、程序实现
1、工程目录
2、在layout 中的布局
xmlns:app="http://schemas.android.com/apk/res-auto">
name="vm"
type="com.sky.customviewforcircle.viewmodel.ProgressBarViewModel" />
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:layout_width="match_parent"
android:layout_height="48dp"
android:gravity="center"
android:orientation="horizontal">
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="自定义半圆形进度条"
android:textColor="@color/pink"
android:textSize="@dimen/sp_20" />
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_50"
android:background="@drawable/vi">
android:id="@+id/progressbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginLeft="@dimen/dp_40"
android:layout_marginRight="@dimen/dp_40"
app:angel="3"
app:front_color="@color/pink"
app:progress="0"
app:show_left_icon="false"
app:show_right_icon="true" />
android:id="@+id/tv_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:textSize="40sp" />
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_50"
android:orientation="horizontal">
android:id="@+id/bt_add"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:onClick="@{(v)->vm.plusMethod(v)}"
android:text="+" />
android:id="@+id/bt_subtract"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:onClick="@{(v)->vm.subtraction(v)}"
android:text="-" />
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_80"
android:gravity="center_vertical"
android:orientation="horizontal">
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="3"
android:background="@color/color_white"
android:hint="请输入进度条数据"
android:inputType="numberDecimal"
android:paddingLeft="@dimen/dp_15"
android:textColor="@color/pink"
android:textSize="@dimen/sp_18"
app:addTextChangedListener="@{vm.textWatcher}" />
android:layout_width="0dp"
android:layout_height="@dimen/dp_50"
android:layout_weight="1"
android:background="@color/pink"
android:gravity="center"
android:onClick="@{(v)->vm.setProgress(v)}"
android:text="确定"
android:textColor="@color/color_white"
android:textSize="@dimen/sp_16" />
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#E0E0E0" />
2、自定义view核心代码
1)获取配置参数public CustomerProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.custom, defStyleAttr, 0);
floatAngel = a.getFloat(R.styleable.custom_angel, 2);
frontColor = a.getColor(R.styleable.custom_front_color,
context.getResources().getColor(R.color.color_white));
bottomColor = a.getColor(R.styleable.custom_back_color,
context.getResources().getColor(R.color.color_white4D));
aimPercent = a.getFloat(R.styleable.custom_progress, 0);
leftBitmap = BitmapFactory.decodeResource(context.getResources(),
a.getResourceId(R.styleable.custom_left_icon, R.drawable.golden_crown));
rightBitmap = BitmapFactory.decodeResource(context.getResources(),
a.getResourceId(R.styleable.custom_right_icon, R.drawable.golden_diamond));
isShowRightIcon = a.getBoolean(R.styleable.custom_show_right_icon, false);
isShowLeftIcon = a.getBoolean(R.styleable.custom_show_left_icon, false);
isShowCurrentPoint = a.getBoolean(R.styleable.custom_show_current_point, true);
a.recycle();
initView(context);
}
2)根据进度条数据创建画布private void drawInsideView(float formDegree, float toDegree, Canvas canvas,
int color, float startDegree, float endDegree) {
shaderPaint.setStrokeWidth(insideArcWidth);
shaderPaint.setStyle(Paint.Style.STROKE);
insideArea = new RectF(width/2 - insideArcRadius, radius-insideArcRadius, width/2
+ insideArcRadius, radius + insideArcRadius);
canvas.drawArc(insideArea, formDegree, toDegree, false, shaderPaint);
if (toDegree != 0) {
if (isShowCurrentPoint) {
Path orbit = new Path();
orbit.addArc(insideArea, formDegree, toDegree);
PathMeasure measure = new PathMeasure(orbit, false);
measure.getPosTan(measure.getLength() * 1, pos, tan);
mMatrix.reset();
mMatrix.postTranslate(pos[0] - mBitmapPoint.getWidth() / 2,
pos[1] - mBitmapPoint.getHeight() / 2);
canvas.drawPath(orbit, shaderPaint);
canvas.drawBitmap(mBitmapPoint, mMatrix, bitmapPaint);
bitmapPaint.setColor(color);
canvas.drawCircle(pos[0], pos[1], 30, bitmapPaint);
}
}
if (isShowLeftIcon) {
Path startorbit = new Path();
startorbit.addArc(insideArea, formDegree, startDegree);
createImgeView(startorbit, canvas, leftBitmap);
}
if (isShowRightIcon) {
Path endOrBit = new Path();
Bitmap endBitmap = rightBitmap;
endOrBit.addArc(insideArea, formDegree, endDegree);
createImgeView(endOrBit, canvas, endBitmap);
}
}
3)实现 onDraw方法(Canvas canvas) {
onDraw(canvas)= getWidth()= / + ScreenUtil. paintPercentBack(canvas)drawPercent(canvas)}
三、实现逻辑
主要是自定义view的思想,结合画布用来实现
1、 先测量高度,控件的高度是又半圆开口到顶端的距离,就是高度
2、重写onDraw方法,在这个方法里面,根据配置参数,判断是否要显示左右两边的图标,然后画底色, 顶部颜色,还有根据坐标点画大圆和小圆,最后在画布上渲染,完成最后的工作
3、可通过动态设置进度条值和进度条前置颜色来满足需求
四、运行效果
1、可在布局设定默认进度值,同时可用+ - 按钮进行加减操作
2、也可以在输入框输入进度值