Android自定义TextView排版优化
今天的文章關于android中最常用的的控件Textview,安卓中的TextView在文字布局的時候會在每行的末尾進行智能的換行分割,特別是有標點符號等出現的時候。這個規律是怎樣的我至今還沒有探究過。有興趣的大家可以自己去看一下TextView的源碼。項目中需要對文字進行較舒服的排布,去掉尾部的空缺,所以我對此給出來自己的解決方案,先看效果圖吧。
綠色字體是用自定義的TextView加載的文字信息,沒有限制最大行數。白色文字是用android系統的TextView。黃色文字是自定義的TextView,限制了最大行數,并且設置了顯示自定義省略信息,就是在布局文件中調用android:ellipsize="end"。效果還是很明顯的
我這里就簡單粗暴的去重寫Textview的onDraw方法了,而且沒有super,完全是自己用Canvas去繪畫每一個文字或者符號。所以一定程度上講,這更像是一個View,丟失了很多TextView的特性,當然為了保留更多的Textview的特性,我也在里面重寫了很多方法,新加入了一些方法。代碼給出來,大家可以根據自己的需要自己去拓展。有很多原來TextView的函數都失去了作用,使用的時候請注意。
import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.widget.TextView;/*** 自定義的文字整齊排版Textview控件,能讓文字相對更加的整齊* <p>* 在xml布局文件中請加入命名空間"http://hdt.hdt/hdt"用于設置以下屬性(單數字不填單位):* lineSpacingExtra,textSize,paddingLeft,paddingRight。 寬度請設置充滿父布局, 目前只支持結尾省略...* * @author illidan.huang 杭州*/ public class MyTextView extends TextView {private final String namespace = "http://hdt.hdt/hdt";private String text;private float textSize;private Paint paint1 = new Paint();private float paddingLeft;private float paddingRight;private float textShowWidth;private int textColor;private float lineSpace;private int maxLines = Integer.MAX_VALUE;private boolean ellipsize = false;private float ellipsizeLength = 0;private String ellipsizeString = "(未完待續...)";// 初始化是否需要設置高度,不加判斷則會無限的遞歸onDraw,自己看private boolean needHieght = true;private int lineCount = 0;public MyTextView(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stubtext = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "text");textSize = attrs.getAttributeIntValue(namespace, "textSize", 10);textColor = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "textColor", Color.WHITE);maxLines = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "maxLines", Integer.MAX_VALUE);String ell = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "ellipsize");ellipsize = "3".equals(ell);//android:ellipsize="end"對應的值是3,請看安卓源碼paddingLeft = attrs.getAttributeIntValue(namespace, "paddingLeft", 0);paddingRight = attrs.getAttributeIntValue(namespace, "paddingRight", 0);lineSpace = attrs.getAttributeIntValue(namespace, "lineSpacingExtra", 3);float d = context.getResources().getDisplayMetrics().density;textSize = d * textSize + 0.5f;lineSpace = d * lineSpace + 0.5f;if(maxLines <= 0){maxLines = Integer.MAX_VALUE;}paint1.setTextSize(textSize);paint1.setColor(textColor);paint1.setAntiAlias(true);textShowWidth = ((Activity) context).getWindowManager().getDefaultDisplay().getWidth() - paddingLeft - paddingRight;ellipsizeLength = paint1.measureText(ellipsizeString);}@Overrideprotected void onDraw(Canvas canvas) {int lineCount = 0;char[] textCharArray = text.toCharArray();float drawedWidth = 0;float charWidth;for (int i = 0; i < textCharArray.length; i++) {charWidth = paint1.measureText(textCharArray, i, 1);// 這里是用于,設置了最大行數和末尾省略的情況下進行的判斷,16完全是我憑感覺給出的數字,沒有為什么if (ellipsize && textShowWidth - drawedWidth - ellipsizeLength < 16) {if (lineCount == maxLines - 1) {canvas.drawText(ellipsizeString, paddingLeft + drawedWidth, (lineCount + 1) * textSize + lineSpace* lineCount, paint1);break;}}// 跳入下一行判斷if (textShowWidth - drawedWidth < charWidth || textCharArray[i] == '\n') {lineCount++;if (lineCount > maxLines - 1) {lineCount--;break;}drawedWidth = 0;}canvas.drawText(textCharArray, i, 1, paddingLeft + drawedWidth, (lineCount + 1) * textSize + lineSpace * lineCount,paint1);drawedWidth += charWidth;}if (needHieght) {setHeight((lineCount + 1) * (int) (textSize + lineSpace));needHieght = false;}this.lineCount = lineCount;}@Overridepublic void invalidate() {needHieght = true;super.invalidate();}@Overridepublic void setText(CharSequence text, BufferType type) {// TODO Auto-generated method stubsuper.setText(text, type);this.text = String.valueOf(text);invalidate();}/*** 設置省略顯示內容,默認"。。。"* * @param ellString*/public final void setEllipsizeString(String ellString) {this.ellipsizeString = ellString;}/*** 設置結尾是否顯示省略內容* * @param isEnd*/public final void setEllipsizeEnd(boolean isEnd) {this.ellipsize = isEnd;}@Overridepublic void setMaxLines(int maxlines) {this.maxLines = maxlines;if(this.maxLines <= 0){this.maxLines = Integer.MAX_VALUE;}super.setMaxLines(maxlines);}@Overridepublic CharSequence getText() {return this.text;}/*** 設置行間距* * @param spa*/public void setLineSpacingExtra(float spa) {this.lineSpace = spa;}@Overridepublic int getLineCount() {return lineCount;}@Overridepublic int getLineHeight() {return (int) (textSize+lineSpace);}@Overridepublic float getTextSize() {return textSize;}@Overridepublic void setSingleLine() {setSingleLine(true);}@Overridepublic void setSingleLine(boolean singleLine) {if(singleLine){setMaxLines(1);}else{setMaxLines(Integer.MAX_VALUE);}}@Overridepublic void setTextColor(int color) {this.textColor = color;paint1.setColor(color);super.setTextColor(color);}}
英文的實現效果我這里暫時未考慮到,需要的話,我給個思路。就是在onDraw函數中,對文字進行分詞的時候
char[] textCharArray = text.toCharArray(); 按單詞為單位進行分割,而不是一個字符char。
以下是圖示的布局文件
若有疑問請下面留言。
若有不足請留言或者聯系我,hdtpjhz@163.com
總結
以上是生活随笔為你收集整理的Android自定义TextView排版优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Timer实现定时任务
- 下一篇: 使用Python开发Android软件