在UI这一块,谈到自定义,就离不开画笔和画布的使用话题,在自定义控件的时候,为了做出炫酷的效果,我们往往会使用画笔和画布,那么这里我们就先来看看画笔的使用吧
简单使用例子
自定义一个View
public class PaintView extends View {
private Paint mPaint;
public PaintView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//重置
mPaint.reset();
//画笔设置
mPaint.setColor(Color.RED);
mPaint.setAlpha(255);
//样式设置
// mPaint.setStyle(Paint.Style.FILL);//填充
mPaint.setStyle(Paint.Style.STROKE);//描边
// mPaint.setStyle(Paint.Style.FILL_AND_STROKE);//填充及描边
//画笔宽度设置
mPaint.setStrokeWidth(20);
//线帽设置
mPaint.setStrokeCap(Paint.Cap.BUTT);//无
// mPaint.setStrokeCap(Paint.Cap.ROUND);//圆形
// mPaint.setStrokeCap(Paint.Cap.SQUARE);//方形
//线条交叉处
// mPaint.setStrokeJoin(Paint.Join.BEVEL);//直角
// mPaint.setStrokeJoin(Paint.Join.ROUND);//圆角
// mPaint.setStrokeJoin(Paint.Join.MITER);//锐角
Path path = new Path();
path.moveTo(100,100);
path.lineTo(300,100);
path.lineTo(500,300);
mPaint.setStrokeJoin(Paint.Join.BEVEL);
canvas.drawPath(path,mPaint);
path.moveTo(100,400);
path.lineTo(300,400);
path.lineTo(500,700);
mPaint.setStrokeJoin(Paint.Join.MITER);
canvas.drawPath(path,mPaint);
path.moveTo(100,800);
path.lineTo(300,800);
path.lineTo(500,1100);
mPaint.setStrokeJoin(Paint.Join.ROUND);
canvas.drawPath(path,mPaint);
}
}
画了三条线
Paint的使用说明
Paint在是使用的时候,一般会有两个类参与,一个负责图形绘制,一个负责文字绘制
在使用前一般重置Paint,调用reset()
设置方法一般都对应着获取方法
图形绘制相关方法
- 设置颜色
mPaint.setColor(Color.RED);
- 设置透明度0~255
mPaint.setAlpha(255);
- 设置画笔的样式
mPaint.setStyle(Paint.Style.FILL);//填充
//mPaint.setStyle(Paint.Style.STROKE);//描边
//mPaint.setStyle(Paint.Style.FILL_AND_STROKE);//填充及描边
- 设置画笔的宽度
mPaint.setStrokeWidth(50);
- 设置线帽
mPaint.setStrokeCap(Paint.Cap.BUTT);//无
//mPaint.setStrokeCap(Paint.Cap.ROUND);//圆形
//mPaint.setStrokeCap(Paint.Cap.SQUARE);//方形
- 设置线条交叉处样式
mPaint.setStrokeJoin(Paint.Join.BEVEL);//直角
//mPaint.setStrokeJoin(Paint.Join.ROUND);//圆角
//mPaint.setStrokeJoin(Paint.Join.MITER);//锐角
- 设置防锯齿
mPaint.setAntiAlias(true);
- 设置图像抖动处理
mPaint.setDither(true);
文字绘制相关方法
- 设置字符行间距
mPaint.setFontSpacing(5);
- 设置字符之间的间距
mPaint.getLetterSpacing(5);
- 设置文本删除线
mPaint.setStrikeThruText(true);
- 设置下划线
mPaint.setUnderlineText(true);
- 设置文本大小
mPaint.setTextSize(textSize);
- 设置字体类型
mPaint.setTypeface(Typeface.BOLD);
- 加载自定义字体
Typeface.create(familyName, style);
- 设置文字倾斜,默认0,官方推荐的
-0.25f
是斜体
mPaint.setTextSkewX(-0.25f);
- 设置文本对齐方式
mPaint.setTextAlign(Align.LEFT);
mPaint.setTextAlign(Align.CENTER);
mPaint.setTextAlign(Align.RIGHT);
- 计算制定长度的字符串(字符长度、字符个数、显示的时候真实的长度)
int breadText = mPaint.breakText(text, measureForwards, maxWidth, measuredWidth);
- 获取文本的矩形区域(宽高)Rect bounds
mPaint.getTextBounds(text, index, count, bounds)
mPaint.getTextBounds(text, start, end, bounds)
- 获取文本的宽度,比较粗略
float measureText = mPaint.measureText(str);
- 获取文本的宽度,比较精准
int textWidths = mPaint.getTextWidths(str, measuredWidth);
文本的基线问题
在绘制文本的时候,事宜基准线为准的,但有时我们在绘制的时候又不以基准线稳准,那么就需要通过计算去获得位置了canvas.drawText(x,y)
这个y并不是text的左上角,而是以baseline为基准的
通过获得相对于基准线的位置,从而计算出需要的位置,负值表示在基准线上方,正值表示在基准线下方
FontMetrics fontMetrics = mPaint.getFontMetrics();
fontMetrics.top;
fontMetrics.ascent;
fontMetrics.descent;
fontMetrics.bottom;
自定义ProgressBar实现
定义自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CustomProgressBar">
<attr name="roundProgressColor" format="color" />
<attr name="roundColor" format="color" />
<attr name="roundWidth" format="dimension" />
<attr name="textSize" format="dimension" />
<attr name="textColor" format="color" />
<attr name="max" format="integer" />
<attr name="min" format="integer" />
<attr name="textShow" format="boolean" />
<attr name="style">
<enum name="STROKE" value="0" />
<enum name="FILL" value="1" />
</attr>
</declare-styleable>
</resources>
自定义ProgressBar
public class CustomProgressBar extends View {
public static final int STROKE = 0;
public static final int FILL = 1;
private int min;
private int roundColor;
private int roundProgressColor;
private float roundWidth;
private int style;
private int textColor;
private boolean textShow;
private float textSize;
private Paint paint;
private int max;
private int progress;
public CustomProgressBar(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
//定义画笔
paint = new Paint();
//获得自定义属性
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomProgressBar);
max = typedArray.getInteger(R.styleable.CustomProgressBar_max, 100);
min = typedArray.getInteger(R.styleable.CustomProgressBar_min, 80);
roundColor = typedArray.getColor(R.styleable.CustomProgressBar_roundColor, Color.RED);
roundProgressColor = typedArray.getColor(R.styleable.CustomProgressBar_roundProgressColor, Color.GRAY);
roundWidth = typedArray.getDimension(R.styleable.CustomProgressBar_roundWidth, 10);
style = typedArray.getInt(R.styleable.CustomProgressBar_style, 0);
textColor = typedArray.getColor(R.styleable.CustomProgressBar_textColor, Color.GREEN);
textShow = typedArray.getBoolean(R.styleable.CustomProgressBar_textShow, true);
textSize = typedArray.getDimension(R.styleable.CustomProgressBar_textSize, 15);
typedArray.recycle();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//画默认的外层圆环
int center = getWidth() / 2;
float radius = center - roundWidth / 2;
paint.setColor(roundColor);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(roundWidth);
paint.setAntiAlias(true);
canvas.drawCircle(center, center, radius, paint);
//画进度百分比
paint.setColor(textColor);
paint.setStrokeWidth(0);
paint.setTextSize(textSize);
paint.setTypeface(Typeface.DEFAULT_BOLD);
int precent = (int) (progress / (float) max * 100);
if (textShow && style == STROKE) {
canvas.drawText(precent + "%", (getWidth() - paint.measureText(precent + "%s")) / 2F,
(getHeight() - (paint.descent() + paint.ascent())) / 2F, paint);
}
//画圆弧
paint.setColor(roundProgressColor);
paint.setStrokeWidth(roundWidth);
RectF oval = new RectF(center - radius, center - radius, center + radius, center + radius);
switch (style) {
case STROKE:
paint.setStyle(Paint.Style.STROKE);
canvas.drawArc(oval, 0, 360 * precent / 100, false, paint);
break;
case FILL:
paint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawArc(oval, 0, 360 * precent / 100, true, paint);
break;
}
}
public int getMin() {
return min;
}
public void setMin(int min) {
this.min = min;
}
public synchronized int getMax() {
return max;
}
public synchronized void setMax(int max) {
if (max < 0) {
throw new IllegalArgumentException("max不能小于0");
}
this.max = max;
}
public synchronized int getProgress() {
return progress;
}
public synchronized void setProgress(int progress) {
if (progress < 0) {
throw new IllegalArgumentException("progress不能小于0");
}
if (progress > max) {
progress = max;
}
if (progress <= max) {
this.progress = progress;
//更新
postInvalidate();
}
}
public int getRoundColor() {
return roundColor;
}
public void setRoundColor(int roundColor) {
this.roundColor = roundColor;
}
public int getRoundProgressColor() {
return roundProgressColor;
}
public void setRoundProgressColor(int roundProgressColor) {
this.roundProgressColor = roundProgressColor;
}
public float getRoundWidth() {
return roundWidth;
}
public void setRoundWidth(float roundWidth) {
this.roundWidth = roundWidth;
}
public int getStyle() {
return style;
}
public void setStyle(int style) {
this.style = style;
}
public int getTextColor() {
return textColor;
}
public void setTextColor(int textColor) {
this.textColor = textColor;
}
public boolean isTextShow() {
return textShow;
}
public void setTextShow(boolean textShow) {
this.textShow = textShow;
}
public float getTextSize() {
return textSize;
}
public void setTextSize(float textSize) {
this.textSize = textSize;
}
}
编写布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myApp="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.cj5785.painttest.CustomProgressBar
android:id="@+id/custom_progress_bar"
android:layout_centerInParent="true"
android:layout_width="100dp"
android:layout_height="100dp"
myApp:roundProgressColor="@android:color/holo_green_light"
myApp:roundColor="@android:color/holo_blue_light"
myApp:roundWidth="10dp"
myApp:textColor="@android:color/holo_orange_light"
myApp:textSize="18sp" />
<Button
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="start"/>
</RelativeLayout>
测试
public class ProgressBarActivity extends AppCompatActivity {
private CustomProgressBar progressBar;
private int progess;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_progress_bar);
progressBar = findViewById(R.id.custom_progress_bar);
}
public void start(View view) {
progess += 5;
progressBar.setProgress(progess);
}
}
效果如下
附录 API
public class Paint extends Object
java.lang.Object
↳android.graphics.Paint
The Paint class holds the style and color information about how to draw geometries, text and bitmaps.
Nested classes | |
---|---|
enum |
Paint.Align Align specifies how drawText aligns its text relative to the [x,y] coordinates. |
enum |
Paint.Cap The Cap specifies the treatment for the beginning and ending of stroked lines and paths. |
class |
Paint.FontMetrics Class that describes the various metrics for a font at a given text size. |
class |
Paint.FontMetricsInt Convenience method for callers that want to have FontMetrics values as integers. |
enum |
Paint.Join The Join specifies the treatment where lines and curve segments join on a stroked path. |
enum |
Paint.Style The Style specifies if the primitive being drawn is filled, stroked, or both (in the same color). |
Constants | |
---|---|
int |
ANTI_ALIAS_FLAG Paint flag that enables antialiasing when drawing. |
int |
DEV_KERN_TEXT_FLAG Legacy Paint flag, no longer used. |
int |
DITHER_FLAG Paint flag that enables dithering when blitting. |
int |
EMBEDDED_BITMAP_TEXT_FLAG Paint flag that enables the use of bitmap fonts when drawing text. |
int |
FAKE_BOLD_TEXT_FLAG Paint flag that applies a synthetic bolding effect to drawn text. |
int |
FILTER_BITMAP_FLAG Paint flag that enables bilinear sampling on scaled bitmaps. |
int |
HINTING_OFF Font hinter option that disables font hinting. |
int |
HINTING_ON Font hinter option that enables font hinting. |
int |
LINEAR_TEXT_FLAG Paint flag that enables smooth linear scaling of text. |
int |
STRIKE_THRU_TEXT_FLAG Paint flag that applies a strike-through decoration to drawn text. |
int |
SUBPIXEL_TEXT_FLAG Paint flag that enables subpixel positioning of text. |
int |
UNDERLINE_TEXT_FLAG Paint flag that applies an underline decoration to drawn text. |
Public constructors |
---|
Paint() Create a new paint with default settings. |
Paint(int flags) Create a new paint with the specified flags. |
Paint(Paint paint) Create a new paint, initialized with the attributes in the specified paint parameter. |
Public methods | |
---|---|
float |
ascent() Return the distance above (negative) the baseline (ascent) based on the current typeface and text size. |
int |
breakText(char[] text, int index, int count, float maxWidth, float[] measuredWidth) Measure the text, stopping early if the measured width exceeds maxWidth. |
int |
breakText(String text, boolean measureForwards, float maxWidth,float[] measuredWidth) Measure the text, stopping early if the measured width exceeds maxWidth. |
int |
breakText(CharSequence text, int start, int end, boolean measureForwards, float maxWidth, float[] measuredWidth) Measure the text, stopping early if the measured width exceeds maxWidth. |
void |
clearShadowLayer() Clear the shadow layer. |
float |
descent() Return the distance below (positive) the baseline (descent) based on the current typeface and text size. |
boolean |
equalsForTextMeasurement(Paint other) Returns true of the passed Paint will have the same effect on text measurement |
int |
getAlpha() Helper to getColor() that just returns the color’s alpha value. |
int |
getColor() Return the paint’s color. |
ColorFilter |
getColorFilter() Get the paint’s colorfilter (maybe be null). |
boolean |
getFillPath(Path src, Path dst) Applies any/all effects (patheffect, stroking) to src, returning the result in dst. |
int |
getFlags() Return the paint’s flags. |
String |
getFontFeatureSettings() Returns the font feature settings. |
float |
getFontMetrics(Paint.FontMetrics metrics) Return the font’s recommended interline spacing, given the Paint’s settings for typeface, textSize, etc. |
Paint.FontMetrics |
getFontMetrics() Allocates a new FontMetrics object, and then calls getFontMetrics(fm) with it, returning the object. |
int |
getFontMetricsInt(Paint.FontMetricsInt fmi) Return the font’s interline spacing, given the Paint’s settings for typeface, textSize, etc. |
Paint.FontMetricsInt |
getFontMetricsInt() |
float |
getFontSpacing() Return the recommend line spacing based on the current typeface and text size. |
String |
getFontVariationSettings() Returns the font variation settings. |
int |
getHinting() Return the paint’s hinting mode. |
float |
getLetterSpacing() Return the paint’s letter-spacing for text. |
MaskFilter |
getMaskFilter() Get the paint’s maskfilter object. |
int |
getOffsetForAdvance(char[] text, int start, int end, int contextStart,int contextEnd, boolean isRtl, float advance) Get the character offset within the string whose position is closest to the specified horizontal position. |
int |
getOffsetForAdvance(CharSequence text, int start, int end, int contextStart, int contextEnd, boolean isRtl, float advance) |
PathEffect |
getPathEffect() Get the paint’s patheffect object. |
float |
getRunAdvance(char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl, int offset) Measure cursor position within a run of text. |
float |
getRunAdvance(CharSequence text, int start, int end, int contextStart,int contextEnd, boolean isRtl, int offset) |
Shader |
getShader() Get the paint’s shader object. |
Paint.Cap |
getStrokeCap() Return the paint’s Cap, controlling how the start and end of stroked lines and paths are treated. |
Paint.Join |
getStrokeJoin() Return the paint’s stroke join type. |
float |
getStrokeMiter() Return the paint’s stroke miter value. |
float |
getStrokeWidth() Return the width for stroking. |
Paint.Style |
getStyle() Return the paint’s style, used for controlling how primitives’ geometries are interpreted (except for drawBitmap, which always assumes FILL_STYLE). |
Paint.Align |
getTextAlign() Return the paint’s Align value for drawing text. |
void |
getTextBounds(String text, int start, int end, Rect bounds) Return in bounds (allocated by the caller) the smallest rectangle that encloses all of the characters, with an implied origin at (0,0). |
void |
getTextBounds(char[] text, int index, int count, Rect bounds) Return in bounds (allocated by the caller) the smallest rectangle that encloses all of the characters, with an implied origin at (0,0). |
Locale |
getTextLocale() Get the text’s primary Locale. |
LocaleList |
getTextLocales() Get the text locale list. |
void |
getTextPath(char[] text, int index, int count, float x, float y, Pathpath) Return the path (outline) for the specified text. |
void |
getTextPath(String text, int start, int end, float x, float y, Pathpath) Return the path (outline) for the specified text. |
float |
getTextScaleX() Return the paint’s horizontal scale factor for text. |
float |
getTextSize() Return the paint’s text size. |
float |
getTextSkewX() Return the paint’s horizontal skew factor for text. |
int |
getTextWidths(char[] text, int index, int count, float[] widths) Return the advance widths for the characters in the string. |
int |
getTextWidths(String text, float[] widths) Return the advance widths for the characters in the string. |
int |
getTextWidths(String text, int start, int end, float[] widths) Return the advance widths for the characters in the string. |
int |
getTextWidths(CharSequence text, int start, int end, float[] widths) Return the advance widths for the characters in the string. |
Typeface |
getTypeface() Get the paint’s typeface object. |
Xfermode |
getXfermode() Get the paint’s transfer mode object. |
boolean |
hasGlyph(String string) Determine whether the typeface set on the paint has a glyph supporting the string. |
final boolean |
isAntiAlias() Helper for getFlags(), returning true if ANTI_ALIAS_FLAG bit is set AntiAliasing smooths out the edges of what is being drawn, but is has no impact on the interior of the shape. |
final boolean |
isDither() Helper for getFlags(), returning true if DITHER_FLAG bit is set Dithering affects how colors that are higher precision than the device are down-sampled. |
boolean |
isElegantTextHeight() Get the elegant metrics flag. |
final boolean |
isFakeBoldText() Helper for getFlags(), returning true if FAKE_BOLD_TEXT_FLAG bit is set |
final boolean |
isFilterBitmap() Whether or not the bitmap filter is activated. |
final boolean |
isLinearText() Helper for getFlags(), returning true if LINEAR_TEXT_FLAG bit is set |
final boolean |
isStrikeThruText() Helper for getFlags(), returning true if STRIKE_THRU_TEXT_FLAG bit is set |
final boolean |
isSubpixelText() Helper for getFlags(), returning true if SUBPIXEL_TEXT_FLAG bit is set |
final boolean |
isUnderlineText() Helper for getFlags(), returning true if UNDERLINE_TEXT_FLAG bit is set |
float |
measureText(char[] text, int index, int count) Return the width of the text. |
float |
measureText(CharSequence text, int start, int end) Return the width of the text. |
float |
measureText(String text, int start, int end) Return the width of the text. |
float |
measureText(String text) Return the width of the text. |
void |
reset() Restores the paint to its default settings. |
void |
set(Paint src) Copy the fields from src into this paint. |
void |
setARGB(int a, int r, int g, int b) Helper to setColor(), that takes a,r,g,b and constructs the color int |
void |
setAlpha(int a) Helper to setColor(), that only assigns the color’s alpha value, leaving its r,g,b values unchanged. |
void |
setAntiAlias(boolean aa) Helper for setFlags(), setting or clearing the ANTI_ALIAS_FLAG bit AntiAliasing smooths out the edges of what is being drawn, but is has no impact on the interior of the shape. |
void |
setColor(int color) Set the paint’s color. |
ColorFilter |
setColorFilter(ColorFilter filter) Set or clear the paint’s colorfilter, returning the parameter. |
void |
setDither(boolean dither) Helper for setFlags(), setting or clearing the DITHER_FLAG bit Dithering affects how colors that are higher precision than the device are down-sampled. |
void |
setElegantTextHeight(boolean elegant) Set the paint’s elegant height metrics flag. |
void |
setFakeBoldText(boolean fakeBoldText) Helper for setFlags(), setting or clearing the FAKE_BOLD_TEXT_FLAG bit |
void |
setFilterBitmap(boolean filter) Helper for setFlags(), setting or clearing the FILTER_BITMAP_FLAG bit. |
void |
setFlags(int flags) Set the paint’s flags. |
void |
setFontFeatureSettings(String settings) Set font feature settings. |
boolean |
setFontVariationSettings(String fontVariationSettings) Sets TrueType or OpenType font variation settings. |
void |
setHinting(int mode) Set the paint’s hinting mode. |
void |
setLetterSpacing(float letterSpacing) Set the paint’s letter-spacing for text. |
void |
setLinearText(boolean linearText) Helper for setFlags(), setting or clearing the LINEAR_TEXT_FLAG bit |
MaskFilter |
setMaskFilter(MaskFilter maskfilter) Set or clear the maskfilter object. |
PathEffect |
setPathEffect(PathEffect effect) Set or clear the patheffect object. |
Shader |
setShader(Shader shader) Set or clear the shader object. |
void |
setShadowLayer(float radius, float dx, float dy, int shadowColor) This draws a shadow layer below the main layer, with the specified offset and color, and blur radius. |
void |
setStrikeThruText(boolean strikeThruText) Helper for setFlags(), setting or clearing the STRIKE_THRU_TEXT_FLAG bit |
void |
setStrokeCap(Paint.Cap cap) Set the paint’s Cap. |
void |
setStrokeJoin(Paint.Join join) Set the paint’s Join. |
void |
setStrokeMiter(float miter) Set the paint’s stroke miter value. |
void |
setStrokeWidth(float width) Set the width for stroking. |
void |
setStyle(Paint.Style style) Set the paint’s style, used for controlling how primitives’ geometries are interpreted (except for drawBitmap, which always assumes Fill). |
void |
setSubpixelText(boolean subpixelText) Helper for setFlags(), setting or clearing the SUBPIXEL_TEXT_FLAG bit |
void |
setTextAlign(Paint.Align align) Set the paint’s text alignment. |
void |
setTextLocale(Locale locale) Set the text locale list to a one-member list consisting of just the locale. |
void |
setTextLocales(LocaleList locales) Set the text locale list. |
void |
setTextScaleX(float scaleX) Set the paint’s horizontal scale factor for text. |
void |
setTextSize(float textSize) Set the paint’s text size. |
void |
setTextSkewX(float skewX) Set the paint’s horizontal skew factor for text. |
Typeface |
setTypeface(Typeface typeface) Set or clear the typeface object. |
void |
setUnderlineText(boolean underlineText) Helper for setFlags(), setting or clearing the UNDERLINE_TEXT_FLAG bit |
Xfermode |
setXfermode(Xfermode xfermode) Set or clear the transfer mode object. |