做之前需要了解一些知识
- 文字宽高获取:一般有以下几种方式
①:设置文字矩形,Paint.getTextBounds方法得到宽高
String test = "Android世界";
Rect rect = new Rect();
mPaint.getTextBounds(text, 0, test.length(), rect);
int width = rect.width();//文字宽
int height = rect.height();//文字高
②获取文字的宽高
首先宽:
String text = getProgress() + "%";
int textWidth = (int) mPaint.measureText(text);
然后高
结论:
//文字的高:
int textHeight = (int) (mPaint.descent() - mPaint.ascent());
分析(参考文章:http://blog.csdn.net/u012551350/article/details/51361778):
ascent = ascent线的y坐标 - baseline线的y坐标;//负数
descent = descent线的y坐标 - baseline线的y坐标;//正数
top = top线的y坐标 - baseline线的y坐标;//负数
bottom = bottom线的y坐标 - baseline线的y坐标;//正数
leading = top线的y坐标 - ascent线的y坐标;//负数
文字的高应该等于asecnt+descent,但是ascent是负的所以mPaint.descent() - mPaint.ascent()
自定义view
package com.yijia.myapplication;
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;
/**
* 项目名:AndFix
* 包名:com.yijia.myapplication
* 文件名:HorizontalProgrssBarWithProgess
* 创建者:周成东
* 创建时间:2018/1/29 19:44
* 描述:ToDo
*/
public class HorizontalProgrssBarWithProgess extends ProgressBar {
private static final int DEFAULT_TEXT_SIZE = 10;//sp
private static final int DEFAULT_TEXT_COLOR = 0XFFC00D1;
private static final int DEFAULT_COLOR_UNREACH = 0XFFD3D6DA;
private static final int DEFAULT_HEIGHT_UNREACH = 2;//dp
private static final int DEFAULT_COLOR_REACH = DEFAULT_TEXT_COLOR;
private static final int DEFAULT_HEIGHT_REACH = 2;//dp
private static final int DEFAULT_TEXT_OFFSET = 10;//dp
private int mTextSize = s2px(DEFAULT_TEXT_SIZE);
private int mTextColor = DEFAULT_TEXT_COLOR;
private int mUnReachColor = DEFAULT_COLOR_UNREACH;
private int mUnReachHeight = d2px(DEFAULT_HEIGHT_UNREACH);
private int mReachColor = DEFAULT_COLOR_REACH;
private int mReachHeight = d2px(DEFAULT_HEIGHT_REACH);
private int mTextOffset = d2px(DEFAULT_TEXT_OFFSET);
private Paint mPaint;
private int mRealWidth;
public HorizontalProgrssBarWithProgess(Context context) {
this(context, null);
}
public HorizontalProgrssBarWithProgess(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public HorizontalProgrssBarWithProgess(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
obtainStyledAttrs(attrs);
mPaint = new Paint();
mPaint.setTextSize(mTextSize);
}
private void obtainStyledAttrs(AttributeSet attrs) {
TypedArray ta = getContext().obtainStyledAttributes(attrs,
R.styleable.HorizontalProgrssBarWithProgess);
mTextSize = (int) ta.getDimension(R.styleable.HorizontalProgrssBarWithProgess_progress_text_size,
mTextSize);
mTextColor = ta.getColor(R.styleable.HorizontalProgrssBarWithProgess_progress_text_color,
mTextColor);
mUnReachColor = ta.getColor(R.styleable.HorizontalProgrssBarWithProgess_progress_unreach_color
, mUnReachColor);
mUnReachHeight = (int) ta.getDimension(R.styleable.HorizontalProgrssBarWithProgess_progress_unreach_height
, mUnReachHeight);
mReachColor = ta.getColor(R.styleable.HorizontalProgrssBarWithProgess_progress_reach_color
, mReachColor);
mReachHeight = (int) ta.getDimension(R.styleable.HorizontalProgrssBarWithProgess_progress_reach_height
, mReachHeight);
mTextOffset = (int) ta.getDimension(R.styleable.HorizontalProgrssBarWithProgess_progress_text_offset,
mTextOffset);
//一定不要忘了回收
ta.recycle();
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//int widhtMode = MeasureSpec.getMode(widthMeasureSpec);
int widhtSize = MeasureSpec.getSize(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
setMeasuredDimension(widhtSize, height);
mRealWidth = widhtSize - getPaddingRight() - getPaddingLeft();
}
private int measureHeight(int heightMeasureSpec) {
int result;
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 = getBottom() + getTop() + Math.max(Math.max(mUnReachHeight, mReachHeight),
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(getLeft(), getHeight() / 2);
boolean noNeedUnRech = false;
float radio = getProgress() * 1.0f / getMax();
float progressX = radio * getWidth();
String text = getProgress() + "%";
int textWidth = (int) mPaint.measureText(text);
if (textWidth + progressX > mRealWidth) {
progressX = mRealWidth - textWidth;
noNeedUnRech = 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);
int y = (int) (-(mPaint.ascent() + mPaint.descent()) / 2);
canvas.drawText(text, progressX, y, mPaint);
//mUnReach bar
if (!noNeedUnRech) {
float startX = progressX + mTextOffset / 2 + textWidth;
mPaint.setColor(mUnReachColor);
mPaint.setStrokeWidth(mUnReachHeight);
canvas.drawLine(startX,0,mRealWidth,0,mPaint);
}
canvas.restore();
}
private int d2px(int dpValue) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue
, getResources().getDisplayMetrics());
}
private int s2px(int spValue) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spValue
, getResources().getDisplayMetrics());
}
}
自定义属性
<?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"/>
<attr name="progress_text_size" format="dimension"/>
<attr name="progress_text_offset" format="dimension"/>
<declare-styleable name="HorizontalProgrssBarWithProgess">
<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>
MainActivity
public class MainActivity extends Activity {
private static final int MSG = 0;
HorizontalProgrssBarWithProgess mProgess;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int progress = mProgess.getProgress();
mProgess.setProgress(++progress);
if (progress >= 100) {
handler.removeMessages(MSG);
}
handler.sendEmptyMessage(MSG);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mProgess = (HorizontalProgrssBarWithProgess) findViewById(R.id.progress);
handler.sendEmptyMessage(MSG);
}
}
布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:yj="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
>
<com.yijia.myapplication.HorizontalProgrssBarWithProgess
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progress="50"
android:padding="5dp"
android:layout_marginTop="30dp"
/>
<com.yijia.myapplication.HorizontalProgrssBarWithProgess
android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progress="50"
android:padding="5dp"
android:layout_marginTop="30dp"
yj:progress_text_color="#44ff0000"
yj:progress_unreach_color="#f000"
yj:progress_reach_color="@color/colorAccent"
/>
</LinearLayout>