Android自定义View (仿计步器)
程序员文章站
2022-06-22 21:20:52
首先让我们来看一下需要实现的效果就是一个很简单的自定义View进入应用圆弧动画过度增加到指定位置并显示步数话不多说我们开搞1.项目结构:2.自定义属性attrs.xml
首先让我们来看一下需要实现的效果
就是一个很简单的自定义View
进入应用圆弧动画过度增加到指定位置并显示步数
话不多说我们开搞
1.项目结构:
2.自定义属性
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyStepView">
<attr name="outerarc_color" format="color"></attr>
<attr name="innerarc_color" format="color"></attr>
<attr name="boorder_width" format="dimension"></attr>
<attr name="steptext_color" format="color"></attr>
<attr name="steptext_size" format="dimension"></attr>
</declare-styleable>
</resources>
3.自定义View 实现思路
- 获取自定义属性值
- 测量布局视图大小
- 绘制圆弧文字
- 设置动画
- 简单基础封装一下
上代码中有详细注释:
MyStepView.java 自定义View
public class MyStepView extends View {
private int mOuterColor;//外圆弧颜色
private int mInnerColor;//内圆弧颜色
private int mBorderWidth;//圆弧宽度
private int mStepTextColor;//显示当前步数颜色
private int mCurrentStep;//当前步数
private int mStepTextSize;//显示当前步数文本
private Paint mOuterPaint;//外圆弧画笔
private Paint mInnerPaint;//内圆弧画笔
private int mMaxStep;//目标步数
private Paint mTextPaint;//文本画笔
private Paint mTextPaintX;//提示信息画笔
private int offset = 0;//动画偏移量
public MyStepView(Context context) {
super(context);
}
public MyStepView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyStepView);//获取自定义属性值
mOuterColor = array.getColor(R.styleable.MyStepView_outerarc_color, mOuterColor);
mInnerColor = array.getColor(R.styleable.MyStepView_innerarc_color, mInnerColor);
mBorderWidth = (int) array.getDimension(R.styleable.MyStepView_boorder_width, 0);
mStepTextColor = array.getColor(R.styleable.MyStepView_steptext_color, mStepTextColor);
mStepTextSize = array.getDimensionPixelSize(R.styleable.MyStepView_steptext_size, mStepTextSize);
array.recycle();//回收
mOuterPaint = new Paint();
mOuterPaint.setAntiAlias(true);
mOuterPaint.setColor(mOuterColor);
mOuterPaint.setStrokeWidth(mBorderWidth);
mOuterPaint.setStyle(Paint.Style.STROKE);
mOuterPaint.setStrokeCap(Paint.Cap.ROUND);
mInnerPaint = new Paint();
mInnerPaint.setAntiAlias(true);
mInnerPaint.setColor(mInnerColor);
mInnerPaint.setStrokeWidth(mBorderWidth);
mInnerPaint.setStyle(Paint.Style.STROKE);
mInnerPaint.setStrokeCap(Paint.Cap.ROUND);
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setColor(mStepTextColor);
mTextPaint.setTextSize(mStepTextSize);
mInnerPaint.setFakeBoldText(true);
mTextPaintX = new Paint();
mTextPaintX.setAntiAlias(true);
mTextPaintX.setColor(mStepTextColor);
mTextPaintX.setTextSize(70);
mTextPaintX.setFakeBoldText(true);
}
public MyStepView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/*测量*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width > height ? height : width, width > height ? height : width);
}
/*绘制*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int center = getWidth() / 2;
int radius = (getWidth() - mBorderWidth) / 2;
RectF rectF = new RectF(mBorderWidth / 2, mBorderWidth / 2, center + radius, center + radius);
canvas.drawArc(rectF, 135, 270, false, mOuterPaint);//绘制内圆弧
if (mMaxStep == 0) {//如果目标值为0 可以不绘制
return;
}
float radio = (float) offset / mMaxStep;
canvas.drawArc(rectF, 135, 270 * radio, false, mInnerPaint);//绘制外圆弧
String mText = offset + "";
Rect rect = new Rect();
mTextPaint.getTextBounds(mText, 0, mText.length(), rect);//获取文本框
int dx = getWidth() / 2 - rect.width() / 2;
canvas.drawText(mText, dx, getWidth() / 2 + rect.height() / 2, mTextPaint);//绘制文字
if (offset == mCurrentStep) {//执行完动画 显示当前步数和目标值
String mTextMax = "今日目标:" + mMaxStep;
String mTextCurrent = "已完成:" + mCurrentStep;
Rect rectMaxstep = new Rect();
Rect rectCurrentStep = new Rect();
mTextPaintX.getTextBounds(mTextMax, 0, mTextMax.length(), rectMaxstep);//获取文本框
mTextPaintX.getTextBounds(mTextCurrent, 0, mTextCurrent.length(), rectCurrentStep);//获取文本框
canvas.drawText(mTextMax, dx - 50, getWidth() + rectMaxstep.height() + 200, mTextPaintX);//绘制文字 今日目标
canvas.drawText(mTextCurrent, dx - 50, getWidth() + rectCurrentStep.height() + 300, mTextPaintX);//绘制文字 已完成
}
}
/*开始动画*/
public void startUi() {
ValueAnimator animator = ObjectAnimator.ofFloat(0, mCurrentStep);//属性动画插值器
animator.addUpdateListener((animation -> {//lambda表达式
float animatedValue = (float) animation.getAnimatedValue();
offset = (int) animatedValue;//实现变化过程
postInvalidate();//重绘刷新整个View
}));
animator.setDuration(3000);//设置动画持续时间
animator.start();//开始执行动画
}
/*设置目标最大值*/
public void setmMaxStep(int mMaxStep) {
this.mMaxStep = mMaxStep;
}
/*设置当前步数*/
public void setmCurrentStep(int mCurrentStep) {
this.mCurrentStep = mCurrentStep;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.example.mryan.stepview.MyStepView
android:id="@+id/myStepView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp"
app:boorder_width="35dp"
app:innerarc_color="@color/yellow"
app:outerarc_color="@color/blue"
app:steptext_color="@color/white"
app:steptext_size="70dp" />
</android.support.constraint.ConstraintLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
private MyStepView myStepView;
@Override
protected void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);/*不显示标题*/
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);/*全屏设置*/
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//强制竖屏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//版本判断
// Translucent status bar
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//设置statusbar应用所占的屏幕扩大到全屏,但是最顶上会有背景透明的状态栏,它的文字可能会盖着你的应用的标题栏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myStepView = findViewById(R.id.myStepView);//绑定
myStepView.setmMaxStep(1500);//设置最大目标
myStepView.setmCurrentStep(1314);//设置当前步数
myStepView.startUi();//开始动画
}
}
简单完成啦!
附上项目链接
本文地址:https://blog.csdn.net/qq_35416214/article/details/106207750