很長時間沒寫技術(shù)文章了,最近一直都很忙吧趣,好不容易周末休息趁有時間寫寫文章看看書,做一個記錄總結(jié)。來看今天的效果强挫,實現(xiàn)一個傾斜角標的展示效果岔霸,先來看下效果圖。
這個效果呢實現(xiàn)起來很簡單俯渤,喊UI幫忙切個圖往xml里一放就好呆细,但是也存在一定的弊端,比如文字失真八匠、屏幕適配等問題絮爷,所以還是代碼實現(xiàn)比較好。一開始的想法是用TextView實現(xiàn)然后旋轉(zhuǎn)45度就好了梨树,但是會有問題坑夯,具體問題自己腦補一下啦~廢話不多說,先放GitHub傳送門:https://github.com/SuperKotlin/CustomTextView
思路
1.canvas旋轉(zhuǎn)45°抡四;
2.獲取文字的高度渊涝,然后根據(jù)文字高度計算背景色高度,賦值給Paint的寬度床嫌;
3.計算出各坐標跨释,使用drawLine畫出背景色,再畫出文字厌处。
說的再多鳖谈,不如一張草圖看得方便~
注:紅色區(qū)域就代表一根線段(drawLine),這是我用了一支很粗的筆畫出來的阔涉。
實現(xiàn)過程
1.先說一下缆娃,這里我是把view設(shè)置為寬高相等的正方形,這樣比較容易理解和實現(xiàn)效果瑰排。那么就在onMeasure方法中把寬高設(shè)置成了一樣的大小贯要。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int size = width < height ? width : height;
/**
* 這里高度要和寬度一致,這樣才能保證效果(不考慮測量模式)
*/
setMeasuredDimension(size, size);
}
2.在onDraw方法中椭住,獲取canvas以view中心點旋轉(zhuǎn)45度
//這里寬高一致崇渗,所以我都寫成了getWidth() ;
canvas.rotate(45, getWidth() / 2, getWidth() / 2);
3.獲取文字高度京郑,然后稍微處理一下賦值給畫背景色塊的畫筆
Paint.FontMetricsInt fontMetricsInt = mPaintText.getFontMetricsInt();
float dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom;
/**
* 這里是設(shè)置文字的背景色塊的高度宅广,根據(jù)文字的高度
*/
float mTextBackGroundHeight = dy * 2 * mOffset;
mPaint.setStrokeWidth(mTextBackGroundHeight);
4.OK,接下來我們就能用畫筆在畫布上作畫了些举,從哪下手就需要精確的坐標點跟狱,我們先來畫紅色背景色部分,那么坐標(起點和終點的X户魏、Y坐標)該怎么計算呢驶臊?
由示意圖可知:有了起點和終點坐標那么我們就可以調(diào)用drawLine(float startX, float startY, float stopX, float stopY, Paint paint)來畫出圖中紅色的區(qū)域了挪挤,但是圖中小x該如何求呢?勾股定理即可:
首先我們可以求出view對角線的長度关翎,再減去邊長(getWidth)扛门,最后再除以2就得出x的長度了。代碼如下:
/**
* 這里是求出背景塊的中心點Y坐標
*/
float startY = (getWidth() - mTextBackGroundHeight) / 2;
/**
* 這里x代表畫布旋轉(zhuǎn)以后笤休,畫筆需要延伸到旋轉(zhuǎn)之前的那個點尖飞,具體請看博客介紹
*/
float x = (float) ((Math.sqrt(2 * getWidth() * getWidth()) - getWidth()) / 2);
canvas.drawLine(-x, startY, getWidth() + x, startY, mPaint);
5.最后在畫出文字,結(jié)束
//畫文字
float mTetxWidth = mPaintText.measureText(mText, 0, mText.length());
float dx = (getWidth() - mTetxWidth) / 2;
canvas.drawText(mText, dx, startY + dy, mPaintText);
完整代碼:
CustomTextView.java:
public class CustomTextView extends View {
private Context mContext;
private Paint mPaintText;
private Paint mPaint;
private String mText = "";//需要繪制的文字
private int mTextColor;
private float mTextSize;
private int mTextBgColor;
private float mOffset = 2f;//背景色的高度偏移量控制值(文字高度的mOffset倍數(shù))
public void setmText(String mText) {
this.mText = mText;
}
public void setmTextBgColor(int mTextBgColor) {
this.mTextBgColor = mTextBgColor;
mPaint.setColor(mTextBgColor);
}
public CustomTextView(Context context) {
this(context, null);
}
public CustomTextView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView);
mText = array.getString(R.styleable.CustomTextView_ct_title_name);
mTextColor = array.getColor(R.styleable.CustomTextView_ct_title_color, Color.WHITE);
mTextSize = array.getDimension(R.styleable.CustomTextView_ct_title_size, sp2px(context, 10));
mTextBgColor = array.getColor(R.styleable.CustomTextView_ct_title_bd_color, Color.RED);
array.recycle();
mPaint = new Paint();
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(mTextBgColor);
mPaintText = new Paint();
mPaintText.setAntiAlias(true);
mPaintText.setColor(mTextColor);
mPaintText.setTextSize(mTextSize);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int size = width < height ? width : height;
/**
* 這里高度要和寬度一致店雅,這樣才能保證效果(不考慮測量模式)
*/
setMeasuredDimension(size, size);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 實現(xiàn)的原理政基,先把畫布以中心點為準旋轉(zhuǎn)45度,
* 然后畫文字闹啦,計算文字的高度沮明,根據(jù)這個高度稍微再擴大一些做為背景條的高度,再畫背景條(一條比較粗的直線)
*/
canvas.rotate(45, getWidth() / 2, getWidth() / 2);
if (!TextUtils.isEmpty(mText)) {
Paint.FontMetricsInt fontMetricsInt = mPaintText.getFontMetricsInt();
float dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom;
/**
* 這里是設(shè)置文字的背景色塊的高度窍奋,根據(jù)文字的高度
*/
float mTextBackGroundHeight = dy * 2 * mOffset;
mPaint.setStrokeWidth(mTextBackGroundHeight);
/**
* 這里是求出背景塊的中心點Y坐標
*/
float startY = (getWidth() - mTextBackGroundHeight) / 2;
/**
* 這里x代表畫布旋轉(zhuǎn)以后荐健,畫筆需要延伸到旋轉(zhuǎn)之前的那個點,具體請看博客介紹
*/
float x = (float) ((Math.sqrt(2 * getWidth() * getWidth()) - getWidth()) / 2);
canvas.drawLine(-x, startY, getWidth() + x, startY, mPaint);
//畫文字
float mTetxWidth = mPaintText.measureText(mText, 0, mText.length());
float dx = (getWidth() - mTetxWidth) / 2;
canvas.drawText(mText, dx, startY + dy, mPaintText);
}
}
public static int sp2px(Context context, float spValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
}
GitHub傳送門:源碼