基于Android 的 自定义半圆进度条
概述
详细
一、项目结构
├─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 中的布局
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="vm" type="com.sky.customviewforcircle.viewmodel.ProgressBarViewModel" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="48dp" android:gravity="center" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="自定义半圆形进度条" android:textColor="@color/pink" android:textSize="@dimen/sp_20" /> </LinearLayout> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/dp_50" android:background="@drawable/vi"> <com.sky.customviewforcircle.widget.CustomerProgressBar 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" /> <TextView 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" /> </FrameLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/dp_50" android:orientation="horizontal"> <Button 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="+" /> <Button 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="-" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/dp_80" android:gravity="center_vertical" android:orientation="horizontal"> <EditText 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}" /> <TextView 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" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="0.5dp" android:background="#E0E0E0" /> </LinearLayout> </LinearLayout> </layout>
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、也可以在输入框输入进度值