Android開發:文字描邊
轉自:http://www.oschina.net/code/snippet_586849_37287
1. [代碼][Java]代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
package
com.example.testproject;
import
android.content.Context;
import
android.graphics.Canvas;
import
android.graphics.Paint.Style;
import
android.text.TextPaint;
import
android.util.AttributeSet;
import
android.view.ViewGroup;
import
android.widget.TextView;
/*
* StrokeTextView的目標是給文字描邊
* 實現方法是兩個TextView疊加,只有描邊的TextView為底,實體TextView疊加在上面
* 看上去文字就有個不同顏色的邊框了
*/
public
class
StrokeTextView
extends
TextView {
private
TextView borderText =
null
;
///用於描邊的TextView
public
StrokeTextView(Context context) {
super
(context);
borderText =
new
TextView(context);
init();
}
public
StrokeTextView(Context context, AttributeSet attrs) {
super
(context, attrs);
borderText =
new
TextView(context,attrs);
init();
}
public
StrokeTextView(Context context, AttributeSet attrs,
int
defStyle) {
super
(context, attrs, defStyle);
borderText =
new
TextView(context,attrs,defStyle);
init();
}
public
void
init(){
TextPaint tp1 = borderText.getPaint();
tp1.setStrokeWidth(
4
);
//設置描邊寬度
tp1.setStyle(Style.STROKE);
//對文字只描邊
borderText.setTextColor(getResources().getColor(R.color.border_text));
//設置描邊顏色
borderText.setGravity(getGravity());
}
@Override
public
void
setLayoutParams (ViewGroup.LayoutParams params){
super
.setLayoutParams(params);
borderText.setLayoutParams(params);
}
@Override
protected
void
onMeasure(
int
widthMeasureSpec,
int
heightMeasureSpec) {
CharSequence tt = borderText.getText();
//兩個TextView上的文字必須一致
if
(tt==
null
|| !tt.equals(
this
.getText())){
borderText.setText(getText());
this
.postInvalidate();
}
super
.onMeasure(widthMeasureSpec, heightMeasureSpec);
borderText.measure(widthMeasureSpec, heightMeasureSpec);
}
protected
void
onLayout (
boolean
changed,
int
left,
int
top,
int
right,
int
bottom){
super
.onLayout(changed, left, top, right, bottom);
borderText.layout(left, top, right, bottom);
}
@Override
protected
void
onDraw(Canvas canvas) {
borderText.draw(canvas);
super
.onDraw(canvas);
}
}
|
2. [代碼][XML]代碼
1
2
3
4
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
resources
>
<
color
name
=
"border_text"
>#ffffff</
color
>
</
resources
>
|
3. [圖片] miao_bian.png

最近在android上搞一個帶描邊效果的TextView,網上搜索了下都是采用兩個TextView在一個layout中進行實現,但細想了下,如果我在一個TextView中讓其以不同的方式進行兩次描繪不就能夠達到效果了嗎?由於網上沒有看到和我類似的方法,故發出來和大家分享,由於只需要重寫protected void onDraw(Canvas canvas);方法即可,故只附上onDraw的實現:
- private boolean m_bDrawSideLine = false; // 默認不采用描邊
- /* (non-Javadoc)
- * @see android.widget.TextView#onDraw(android.graphics.Canvas)
- */
- @Override
- protected void onDraw(Canvas canvas) {
- if (m_bDrawSideLine) {
- // 描外層
- //super.setTextColor(Color.BLUE); // 不能直接這么設,如此會導致遞歸
- setTextColorUseReflection(Color.BLUE);
- m_TextPaint.setStrokeWidth(3); // 描邊寬度
- m_TextPaint.setStyle(Style.FILL_AND_STROKE); //描邊種類
- m_TextPaint.setFakeBoldText(true); // 外層text采用粗體
- m_TextPaint.setShadowLayer(1, 0, 0, 0); //字體的陰影效果,可以忽略
- super.onDraw(canvas);
- // 描內層,恢復原先的畫筆
- //super.setTextColor(Color.BLUE); // 不能直接這么設,如此會導致遞歸
- setTextColorUseReflection(Color.RED);
- m_TextPaint.setStrokeWidth(0);
- m_TextPaint.setStyle(Style.FILL_AND_STROKE);
- m_TextPaint.setFakeBoldText(false);
- m_TextPaint.setShadowLayer(0, 0, 0, 0);
- }
- super.onDraw(canvas);
- }
- private void setTextColorUseReflection(int color) {
- Field textColorField;
- try {
- textColorField = TextView.class.getDeclaredField("mCurTextColor");
- textColorField.setAccessible(true);
- textColorField.set(color);
- textColorField.setAccessible(false);
- } catch (NoSuchFieldException e) {
- e.printStackTrace();
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- m_TextPaint.setColor(color);
- }
以上代碼中m_bDrawSideLine為false即和一般的textView無異,只需要將其改為true即可看到描邊效果。以上,我只是拋磚引玉,以下發一個小圖吧。
package com.zg.mrcheney;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.util.AttributeSet;
import android.widget.TextView;
public class StrokeText extends TextView {
private float mBigFontBottom;
private float mBigFontHeight;
private String text;
private Paint mPaint;
private int strokeSize = 1;
public StrokeText(Context context) {
super(context);
init();
}
public StrokeText(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public StrokeText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setTextSize(getTextSize());
mPaint.setColor(getResources().getColor(R.color.font_paint_color));
FontMetrics fm = mPaint.getFontMetrics();
mBigFontBottom = fm.bottom;
mBigFontHeight = fm.bottom - fm.top;
}
@Override
protected void onDraw(Canvas canvas) {
if (strokeSize > 0 && strokeSize < 4) {
float y = getPaddingTop() + mBigFontHeight - mBigFontBottom;
canvas.drawText(text, 0, y - strokeSize, mPaint);
canvas.drawText(text, 0, y + strokeSize, mPaint);
canvas.drawText(text, 0 + strokeSize, y, mPaint);
canvas.drawText(text, 0 + strokeSize, y + strokeSize, mPaint);
canvas.drawText(text, 0 + strokeSize, y - strokeSize, mPaint);
canvas.drawText(text, 0 - strokeSize, y, mPaint);
canvas.drawText(text, 0 - strokeSize, y + strokeSize, mPaint);
canvas.drawText(text, 0 - strokeSize, y - strokeSize, mPaint);
}
super.onDraw(canvas);
}
@Override
public void setText(CharSequence text, BufferType type) {
super.setText(text, type);
this.text = text.toString();
invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (strokeSize > 0 && strokeSize < 4) {
setMeasuredDimension(getMeasuredWidth() + strokeSize, getMeasuredHeight());
}
}
}