Android實(shí)現(xiàn)TextView兩端對(duì)齊的方法
Android中的TextView控件默認(rèn)是做不到兩端對(duì)齊的,都是左對(duì)齊。可能的原因是安卓默認(rèn)數(shù)字、字母不能為第一行以后每行的開頭字符,因?yàn)閿?shù)字、字母為半角字符,還有就是文字中的英文字符占用1個(gè)字節(jié),而一個(gè)漢字占用兩個(gè)字節(jié)。下面我就介紹下實(shí)現(xiàn)兩端對(duì)齊的原理:
- 1、測(cè)量一個(gè)中文漢字所占用的寬度
- 2、根據(jù)TextView的寬度和一個(gè)漢字所占用的寬度以及字符之間的間隔計(jì)算出總行數(shù)。
- 3、根據(jù)padding和margin以及行高計(jì)算出TextView的總高度。
- 4、繪制每一行的每一個(gè)字符
效果如下:

具體代碼如下:
package com.wedroid.framework.module.ui;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.ViewGroup.MarginLayoutParams;
import android.view.ViewTreeObserver.OnPreDrawListener;
import android.widget.TextView;
public class WeDroidAlignTextView extends TextView {
private boolean first = true;
public WeDroidAlignTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
@Override
public boolean onPreDraw() {
initTextInfo();
return true;
}
});
}
public WeDroidAlignTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public WeDroidAlignTextView(Context context) {
this(context, null, 0);
}
private float textSize;
private float textLineHeight;
private int top;
private int y;
private int lines;
private int bottom;
private int right;
private int left;
private int lineDrawWords;
private char[] textCharArray;
private float singleWordWidth;
private float lineSpacingExtra;
public void initTextInfo() {
textSize = getTextSize();
textLineHeight = getLineHeight();
left = 0;
right = getRight();
y = getTop();
// 要畫的寬度
int drawTotalWidth = right - left;
String text = getText().toString();
if (!TextUtils.isEmpty(text) && first) {
textCharArray = text.toCharArray();
TextPaint mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.density = getResources().getDisplayMetrics().density;
mTextPaint.setTextSize(textSize);
// 一個(gè)單詞的的寬度
singleWordWidth = mTextPaint.measureText("一") + lineSpacingExtra;
// 一行可以放多少個(gè)字符
lineDrawWords = (int) (drawTotalWidth / singleWordWidth);
int length = textCharArray.length;
lines = length / lineDrawWords;
if ((length % lineDrawWords) > 0) {
lines = lines + 1;
}
first = false;
MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();
int totalHeight = (int) (lines*textLineHeight+textLineHeight*2 + getPaddingBottom()+getPaddingTop()+layoutParams.bottomMargin+layoutParams.topMargin);
setHeight(totalHeight);
}
}
@Override
protected void onDraw(Canvas canvas) {
bottom = getBottom();
int drawTotalLine = lines;
if(maxLine!=0&&drawTotalLine>maxLine){
drawTotalLine = maxLine;
}
for (int i = 0; i < drawTotalLine; i++) {
try {
int length = textCharArray.length;
int mLeft = left;
// 第i+1行開始的字符index
int startIndex = (i * 1) * lineDrawWords;
// 第i+1行結(jié)束的字符index
int endTextIndex = startIndex + lineDrawWords;
if (endTextIndex > length) {
endTextIndex = length;
y += textLineHeight;
} else {
y += textLineHeight;
}
for (; startIndex < endTextIndex; startIndex++) {
char c = textCharArray[startIndex];
// if (c == ' ') {
// c = '\u3000';
// } else if (c < '\177') {
// c = (char) (c + 65248);
// }
canvas.drawText(String.valueOf(c), mLeft, y, getPaint());
mLeft += singleWordWidth;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
int maxLine;
public void setMaxLines(int max){
this.maxLine = max;
}
public void setLineSpacingExtra(int lineSpacingExtra){
this.lineSpacingExtra = lineSpacingExtra;
}
/**
* 判斷是否為中文
* @return
*/
public static boolean containChinese(String string){
boolean flag = false;
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
if ((c >= 0x4e00) && (c <= 0x9FA5)) {
flag = true;
}
}
return flag;
}
public static String ToDBC(String input) {
// 導(dǎo)致TextView異常換行的原因:安卓默認(rèn)數(shù)字、字母不能為第一行以后每行的開頭字符,因?yàn)閿?shù)字、字母為半角字符
// 所以我們只需要將半角字符轉(zhuǎn)換為全角字符即可
char c[] = input.toCharArray();
for (int i = 0; i < c.length; i++) {
if (c[i] == ' ') {
c[i] = '\u3000';
} else if (c[i] < '\177') {
c[i] = (char) (c[i] + 65248);
}
}
return new String(c);
}
}
希望本文所述對(duì)大家學(xué)習(xí)Android程序設(shè)計(jì)有所幫助。
相關(guān)文章
Android編程中ViewPage判斷左右滑動(dòng)方向的方法
這篇文章主要介紹了Android編程中ViewPage判斷左右滑動(dòng)方向的方法,涉及Android中ViewPage針對(duì)滑動(dòng)判定的相關(guān)技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-10-10
Android實(shí)現(xiàn)簡(jiǎn)單的答題系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)簡(jiǎn)單的答題系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01
android Tween Animation屬性設(shè)置方法實(shí)例
在Android開發(fā)中,Animation是用來(lái)給控件制作效果的,本文介紹二種實(shí)現(xiàn)方法2013-11-11
Android EditText長(zhǎng)按菜單中分享功能的隱藏方法
Android EditText控件是經(jīng)常使用的控件,下面這篇文章主要給大家介紹了關(guān)于Android中EditText長(zhǎng)按菜單中分享功能的隱藏方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02
Android RecyclerView使用GridLayoutManager間距設(shè)置的方法
本篇文章主要介紹了Android RecyclerView使用GridLayoutManager間距設(shè)置的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12
Android自定義狀態(tài)欄顏色與應(yīng)用標(biāo)題欄顏色一致
看IOS上的應(yīng)用,應(yīng)用中狀態(tài)欄的顏色總能與應(yīng)用標(biāo)題欄顏色保持一致,用戶體驗(yàn)很不錯(cuò),對(duì)于這種效果怎么實(shí)現(xiàn)的呢?下面小編給大家分享android自定義狀態(tài)欄顏色與應(yīng)用標(biāo)題欄顏色一致的實(shí)現(xiàn)方法,一起看看吧2016-09-09
Android View.onMeasure方法詳解及實(shí)例
這篇文章主要介紹了Android View.onMeasure方法詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-05-05

