標籤:android 繪圖 canvas paint
前言
上一節,學會了Paint,Canvas的基本用法後,這一節,學習Paint的進階用法。還沒看過上一節的請點擊這裡:Android_2D繪圖的學習Paint,Canvas(一)。
一,文字的繪製
在做UI的時候,常常會繪製文字,Canvas繪製文字時,主要考慮到字型的寬度和高度問題。字型的寬度比較好理解,這裡我們主要考慮一下字型的高度。
先看一張圖,網上搜的:
這裡說明了在安卓中繪製字型時對於高度的劃分:top,ascent,baseLine,descent,bottom.有點類似我們剛開始學英語的時候的練習本。字型的高度我們取得是ascent到descent的距離。經過我測試,系統內建的TextView中,繪製的背景高度為top到bottom的距離。字型的起始座標點預設是baseLine中最左邊的一個點,可以通過調用Paint.setTextAlign(Paint.Align align)方法設定中間還是最右邊。
我們先來繪製一個正確的文字置中的一個效果:
代碼:
private Paint mPaint; private String mText = "Android Paint學習"; public PaintView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mPaint = new Paint(); mPaint.setColor(Color.BLACK); mPaint.setTextSize(TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 20, getResources() .getDisplayMetrics())); } public PaintView(Context context, AttributeSet attrs) { this(context, attrs, 0); // TODO Auto-generated constructor stub } public PaintView(Context context) { this(context, null); // TODO Auto-generated constructor stub } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //得到文字寬度 int textWidth = (int) mPaint.measureText(mText); //得到文字高度 int textHeight = (int) (mPaint.descent() - mPaint.ascent()); // 設定View的高度和寬度為字型的高度和寬度 widthMeasureSpec = MeasureSpec.makeMeasureSpec(textWidth, MeasureSpec.EXACTLY); heightMeasureSpec = MeasureSpec.makeMeasureSpec(textHeight, MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { //這裡減去了一個descent主要是畫筆畫文字的基準線為baseLine,如果不剪,就會出現底部有一部分看不到的情況 canvas.drawText(mText, 0, getHeight() - mPaint.descent(), mPaint); }
明顯可以看出系統的TextView要高一點。注意top和ascent的值都是負值,所以在擷取高度時,是減去ascent。如果要像TextView一樣的高度的方法代碼:
FontMetrics fm = mPaint.getFontMetrics();int textHeight = (int) (fm.descent - fm.top+2);
因為Paint沒有top()這個方法所以我們用FontMetrics中的top屬性。
這裡參考了一篇博文:Android字型高度的研究講的很詳細的。
二,Paint.Cap
The Cap specifies the treatment for the beginning and ending of stroked lines and paths. The default is BUTT.
cap是帽子,覆蓋的意思,在畫筆中,就是指定邊緣點(畫筆第一點,和畫筆最後一點)的樣式。
一共有3種樣式:BUTT,ROUND,SQUARE.
我都以畫一段圓弧來說明,效果:
從左至右分別是:SQUARE,ROUND,BUTT一看圖,就瞭然了。
代碼:
mPaint.setColor(Color.RED); mPaint.setStrokeWidth(2); canvas.drawLine(0, 50, getWidth(), 50, mPaint); mPaint.setStrokeWidth(30); mPaint.setStyle(Style.STROKE); mPaint.setAntiAlias(true); mPaint.setColor(Color.BLACK); mPaint.setStrokeCap(Cap.BUTT); canvas.drawArc(new RectF(-getWidth() + 150, -getHeight() + 150, getWidth() - 50, getHeight() - 50), 0, 50, false, mPaint); mPaint.setStrokeCap(Cap.ROUND); canvas.drawArc(new RectF(-getWidth() + 100, -getHeight() + 150, getWidth() - 100, getHeight() - 50), 0, 50, false, mPaint); mPaint.setStrokeCap(Cap.SQUARE); canvas.drawArc(new RectF(-getWidth() + 50, -getHeight() + 150, getWidth() - 150, getHeight() - 50), 0, 50, false, mPaint);
三,Paint.join
The Join specifies the treatment where lines and curve segments join on a stroked path. The default is MITER.
摘自官方文檔,就是說路徑在轉彎的時候指定其樣式。
一共有3種樣式:MITER,ROUND,BEVEL。
效果:
從左至右分別是:MITER,ROUND,BEVEL。
代碼:
mPaint.setStrokeWidth(40); mPaint.setStyle(Style.STROKE); mPaint.setStrokeJoin(Join.MITER); Path path = new Path(); path.moveTo(0, 30); path.lineTo(100, 30); path.lineTo(100, 100); canvas.drawPath(path, mPaint); mPaint.setStrokeJoin(Join.ROUND); Path path1 = new Path(); path1.moveTo(200, 30); path1.lineTo(300, 30); path1.lineTo(300, 100); canvas.drawPath(path1, mPaint); mPaint.setStrokeJoin(Join.BEVEL); Path path2 = new Path(); path2.moveTo(400, 30); path2.lineTo(500, 30); path2.lineTo(500, 100); canvas.drawPath(path2, mPaint);
四,Paint.FontMetrics
調用Paint.getFontMetrics()會返回一個FontMetrics對象,調用前記得先設定字型大小,該對象有5個屬性,分別是:top,ascent,descent,bottom,leading(行間距).注意前2個的值為負。
Android_2D繪圖的學習Paint,Canvas(二)