在学习自定义view之前我们必须先来了解一下attrs.xml这个文件,这个文件实际上定义了所有的控件的属性,就是我们在布局文件中设置的各类属性,因此在自定义控件属性的时候,创建一个attrs.xml文件来定义控件属性是十分重要的,下面我们开始进行项目的第一部分
一、attrs.xml文件的编写
首先在values文件下新建attrs.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--属性的申明-->
<attr name="progress_unreach_color" format="color"/> //没有到达的时候进度条的颜色
<attr name="progress_unreach_height" format="dimension"/>
<attr name="progress_reach_color" format="color"/>
<attr name="progress_reach_height" format="dimension"/>
<attr name="progress_text_color" format="color"/> //<span style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px;">format的意思是说:这个textColor可以以两种方式设置,要么是关联一个值,要么<span style="white-space:pre"> </span>//是直接设置一个颜色的RGB值,这个不难理解,因为我们可以平时也这样做过。</span>
<attr name="progress_text_size" format="dimension"/>
<attr name="progress_text_offset" format="dimension"/> //文本与两边的距离
<!--属性的使用,不需要formet-->
<declare-styleable name="HorizontalProgressBar">
<attr name="progress_unreach_color" />
<attr name="progress_unreach_height" />
<attr name="progress_reach_color" />
<attr name="progress_reach_height"/>
<attr name="progress_text_color" />
<attr name="progress_text_size" />
<attr name="progress_text_offset" /> //文本与两边的距离
</declare-styleable>
</resources>
接下来是自定义view class的编写以及view的绘制
package com.ricahrd.customprogressbar.view; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.util.AttributeSet; import android.util.TypedValue; import android.widget.ProgressBar; import com.ricahrd.customprogressbar.R; /** * Created by jiangwei on 16/5/23. */ public class HorizontalProgressBar extends ProgressBar { private static final int DEFAULT_TEXT_SIZE = 10; //sp private static final int DEFAULT_TEXT_COLOR = 0xFFFC00D1; private static final int DEFAULT_COLOR_UNREACH = 0XFFD3D6DA; private static final int DEFAULT_HEIGHT_UNREACH = 2; //dp private static final int DEFAULT_COLOR_REACH = 0xFFFC00D1; private static final int DEFAULT_HEIGHT_REACH = 2; //dp private static final int DEFAULT_TEXT_OFFSET = 10; //dp //自定义所需成员变量 private int mTextSize = sp2px(DEFAULT_TEXT_SIZE); private int mTextColor = DEFAULT_TEXT_COLOR; private int mUnReachColor = DEFAULT_COLOR_UNREACH; private int mUnReachHeight = dp2px(DEFAULT_HEIGHT_UNREACH); private int mReachColor = DEFAULT_COLOR_REACH; private int mReachHeight = dp2px(DEFAULT_HEIGHT_REACH); private int mTextOffSet = dp2px(DEFAULT_TEXT_OFFSET); private Paint mPaint = new Paint(); private int mRealWidth; public HorizontalProgressBar(Context context) { this(context, null); } public HorizontalProgressBar(Context context, AttributeSet attrs) { super(context, attrs, 0); } public HorizontalProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); obtainStyleAttrs(attrs); } /** * 获取自定义属性 * * @param attrs */ private void obtainStyleAttrs(AttributeSet attrs) { TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.HorizontalProgressBar); mTextSize = (int) ta.getDimension(R.styleable.HorizontalProgressBar_progress_text_size , mTextSize); mTextColor = ta.getColor(R.styleable.HorizontalProgressBar_progress_text_color, mTextColor); mTextOffSet = (int) ta.getDimension(R.styleable.HorizontalProgressBar_progress_text_offset, mTextOffSet); mUnReachColor = ta.getColor(R.styleable.HorizontalProgressBar_progress_unreach_color, mUnReachColor); mUnReachHeight = (int) ta.getDimension(R.styleable.HorizontalProgressBar_progress_unreach_height, mUnReachHeight); mReachColor = ta.getColor(R.styleable.HorizontalProgressBar_progress_reach_color, mReachColor); mReachHeight = (int) ta.getDimension(R.styleable.HorizontalProgressBar_progress_reach_height, mReachHeight); ta.recycle(); mPaint.setTextSize(mTextSize); } @Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //宽度默认用户一定会给一个确定的值 // int widthMod = MeasureSpec.getMode(widthMeasureSpec); int widthVal = MeasureSpec.getSize(widthMeasureSpec); int height = measureHeight(heightMeasureSpec); setMeasuredDimension(widthVal, height); mRealWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); } //测量高度 private int measureHeight(int heightMeasureSpec) { int result = 0; int mode = MeasureSpec.getMode(heightMeasureSpec); int size = MeasureSpec.getSize(heightMeasureSpec); //用户给具体值 if (mode == MeasureSpec.EXACTLY) { result = size; } else { int textheight = (int) (mPaint.descent() - mPaint.ascent()); result = getPaddingBottom() + getPaddingTop() + Math.max(Math.max(mReachHeight, mUnReachHeight), Math.abs(textheight)); if (mode == MeasureSpec.AT_MOST) { result = Math.min(result, size); } } return result; } @Override protected synchronized void onDraw(Canvas canvas) { canvas.save(); canvas.translate(getPaddingLeft(), getHeight() / 2); boolean noneedUnReach = false; String text = getProgress() + "%"; //达到的长度百分比 float radio = getProgress() * 1.0f / getMax(); float progressX = radio * mRealWidth; int textwidth = (int) mPaint.measureText(text); if (progressX + textwidth > mRealWidth) { progressX = mRealWidth - textwidth; noneedUnReach = true; } float endx = progressX - mTextOffSet / 2; if (endx > 0) { mPaint.setColor(mReachColor); mPaint.setStrokeWidth(mReachHeight); canvas.drawLine(0, 0, endx, 0, mPaint); } //drawtext mPaint.setColor(mTextColor); mPaint.setTextSize(mTextSize); int y = (int) -(mPaint.descent() + mPaint.ascent()) / 2; canvas.drawText(text, progressX, y, mPaint); //draw unreachbar if (!noneedUnReach) { float start = progressX + mTextOffSet / 2 + textwidth; mPaint.setColor(mUnReachColor); mPaint.setStrokeWidth(mUnReachHeight); canvas.drawLine(start, 0, mRealWidth, 0, mPaint); } canvas.restore(); } //dp转换成int的方法 public int dp2px(int dpVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, getResources().getDisplayMetrics()); } //sp转换成int的方法 public int sp2px(int spVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal, getResources().getDisplayMetrics()); } }
布局文件activity_main.xml:
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:hyman="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <com.ricahrd.customprogressbar.view.HorizontalProgressBar android:id="@+id/progress_01" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:padding="5dp" hyman:progress_reach_color="#ffff0000" hyman:progress_text_color="#ffff0000" hyman:progress_unreach_color="#44ff0000" android:progress="40" /> </LinearLayout> </ScrollView>
实现效果:
这就是一个简单的自定义水平进度条工程,欢迎大家与我交流~~~