1、概述
1.1 目的 :
在我们的日常开发中,有很多Android UI界面上有一些特殊或者特别的控件与界面,是Android自带的控件所不能满足的,需要我们自己定制一些适合的控件来完成。
1.2 Android自定义View步骤 :
- 自定义属性;
- 选择和设置构造方法;
- 重写onMeasure()方法(确定 view 大小);
- 重写onDraw()方法(确定 view 内容);
- 重写onLayout()方法(确定 view 位置);
- 重写其他事件的方法(滑动监听等)。
2、代码实现
2.1 自定义属性:
我们通常将自定义属性定义在/values/attr.xml文件中(attr.xml文件需要自己创建)。
<declare-styleable name="UpdataAPPProgressBar">
<attr name="updataAPPReachedBarColor" format="color" />
<attr name="updataAPPUnreachedBarColor" format="color" />
<attr name="updataAPPTextColor" format="color" />
<attr name="updataAPPBarHeight" format="dimension"/>
<attr name="updataAPPMax" format="integer" />
<attr name="updataAPPProgress" format="integer" />
<attr name="updataAPPSuffix" format="string" />
<attr name="updataAPPPrefix" format="string" />
<attr name="updataAPPTextVisibility" format="boolean"/>
</declare-styleable>
2.2 实现方法含义
1、在OnMeasure()方法中,测量自定义控件的大小,使自定义控件能够自适应布局各种各样的需求。
2、在OnDraw()方法中,利用哼哈二将(Canvas与Paint)来绘制要显示的内容。
3、在OnLayout()方法中来确定控件显示位置。
4、在OnTouchEvent()方法处理控件的触摸事件。、
2.3 继承View实现代码
package com.fly.myview.progressbar;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import com.fly.myview.R;
import java.text.DecimalFormat;
import java.util.HashMap;
/**
* <pre>
* .----.
* _.'__ `.
* .--(Q)(OK)---/$\
* .' @ /$$$\
* : , $$$$$
* `-..__.-' _.-\$$/
* `;_: `"'
* .'"""""`.
* /, FLY ,\
* // \\
* `-._______.-'
* ___`. | .'___
* (______|______)
* </pre>
* 包 名 : com.fly.myview.progressbar
* 作 者 : FLY
* 创建时间 : 2018/9/6
* 描述: 更新下载的进度条
*/
public class UpdataAPPProgressBar extends View {
/**
* 进度条最大值
*/
private float mMax = 100;
/**
* 进度条当前进度值
*/
private float mProgress = 0;
/**
* 默认已完成颜色
*/
private final int DEFAULT_FINISHED_COLOR = getResources().getColor(R.color.arc_progress_finished_color);
/**
* 默认未完成颜色
*/
private final int DEFAULT_UNFINISHED_COLOR = getResources().getColor(R.color.arc_progress_unfinished_color);
/**
* 已完成进度颜色
*/
private int mReachedBarColor;
/**
* 未完成进度颜色
*/
private int mUnreachedBarColor;
/**
* 进度条高度
*/
private float mBarHeight;
/**
* the progress text color.
*/
private int mTextColor;
/**
* 后缀
*/
private String mSuffix = "%";
/**
* 前缀
*/
private String mPrefix = "";
/**
* 未完成进度条所在矩形区域
*/
private RectF mUnreachedRectF = new RectF(0, 0, 0, 0);
/**
* 已完成进度条所在矩形区域
*/
private RectF mReachedRectF = new RectF(0, 0, 0, 0);
/**
* 画笔
*/
private Paint mPaint;
private boolean mTextVisibility;
public UpdataAPPProgressBar(Context context) {
this(context, null);
}
public UpdataAPPProgressBar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public UpdataAPPProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttrs(context, attrs);
initPainters();
}
private void initAttrs(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.UpdataAPPProgressBar);
mMax = typedArray.getInteger(R.styleable.UpdataAPPProgressBar_updataAPPMax, (int) mMax);
mProgress = typedArray.getInteger(R.styleable.UpdataAPPProgressBar_updataAPPProgress, (int) mProgress);
mReachedBarColor = typedArray.getColor(R.styleable.UpdataAPPProgressBar_updataAPPReachedBarColor, DEFAULT_FINISHED_COLOR);
mUnreachedBarColor = typedArray.getColor(R.styleable.UpdataAPPProgressBar_updataAPPUnreachedBarColor, DEFAULT_UNFINISHED_COLOR);
mTextColor = typedArray.getColor(R.styleable.UpdataAPPProgressBar_updataAPPTextColor, DEFAULT_UNFINISHED_COLOR);
mSuffix = TextUtils.isEmpty(typedArray.getString(R.styleable.UpdataAPPProgressBar_updataAPPSuffix)) ? mSuffix : typedArray.getString(R.styleable.UpdataAPPProgressBar_updataAPPSuffix);
mPrefix = TextUtils.isEmpty(typedArray.getString(R.styleable.UpdataAPPProgressBar_updataAPPPrefix)) ? mPrefix : typedArray.getString(R.styleable.UpdataAPPProgressBar_updataAPPPrefix);
mBarHeight = typedArray.getDimension(R.styleable.UpdataAPPProgressBar_updataAPPBarHeight, dp2px(2f));
mTextVisibility = typedArray.getBoolean(R.styleable.UpdataAPPProgressBar_updataAPPTextVisibility, true);
typedArray.recycle();
}
private void initPainters() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//抗锯齿
mPaint.setAntiAlias(true);//防抖动
mPaint.setStrokeCap(Paint.Cap.ROUND);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
calculateDrawRectFWithoutProgressText();
mPaint.setColor(mUnreachedBarColor);
canvas.drawRoundRect(mUnreachedRectF, mBarHeight / 2, mBarHeight / 2, mPaint);
mPaint.setColor(mReachedBarColor);
canvas.drawRoundRect(mReachedRectF, mBarHeight / 2, mBarHeight / 2, mPaint);
mPaint.setColor(mTextColor);
mPaint.setTextSize(mBarHeight * 0.6f);
String mCurrentDrawText = new DecimalFormat("#").format(getProgress() * 100 / getMax());
mCurrentDrawText = mPrefix + mCurrentDrawText + mSuffix;
float mDrawTextWidth = mPaint.measureText(mCurrentDrawText);
if (mTextVisibility && getProgress() > 0 && mReachedRectF.right >mDrawTextWidth) {
canvas.drawText(mCurrentDrawText, mReachedRectF.right - mDrawTextWidth - mBarHeight * 0.4f, (int) ((getHeight() / 2.0f) - ((mPaint.descent() + mPaint.ascent()) / 2.0f)), mPaint);
}
}
private void calculateDrawRectFWithoutProgressText() {
mReachedRectF.left = getPaddingLeft();
mReachedRectF.top = getHeight() / 2.0f - mBarHeight / 2.0f;
mReachedRectF.right = (getWidth() - getPaddingLeft() - getPaddingRight()) / (getMax() * 1.0f) * getProgress() + getPaddingLeft();
mReachedRectF.bottom = getHeight() / 2.0f + mBarHeight / 2.0f;
mUnreachedRectF.left = getPaddingLeft();
mUnreachedRectF.top = getHeight() / 2.0f + -mBarHeight / 2.0f;
mUnreachedRectF.right = getWidth() - getPaddingRight();
mUnreachedRectF.bottom = getHeight() / 2.0f + mBarHeight / 2.0f;
}
public float getMax() {
return mMax;
}
public float getProgress() {
return mProgress;
}
public void setMax(int max) {
this.mMax = max;
invalidate();
}
public void setProgress(float progress) {
this.mProgress = checkProgress(progress);
invalidate();
}
private float checkProgress(float progress) {
if (progress < 0) return 0;
return progress > mMax ? mMax : progress;
}
private int dp2px(float dpValue) {
float scale = getContext().getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
3、使用
<com.fly.myview.progressbar.UpdataAPPProgressBar
android:id="@+id/updata"
android:layout_width="match_parent"
android:layout_height="20dp"
app:updataAPPBarHeight="20dp"
android:padding="@dimen/dp_10"
app:updataAPPMax="100"
app:updataAPPProgress="0"
app:updataAPPReachedBarColor="#FF6770"
app:updataAPPUnreachedBarColor="#EBEBEB"
app:updataAPPTextColor="@color/color_white" />
4.效果
希望对各位朋友有帮助,谢谢!!!!