方法一(Util包):
/**
* 解决文本中有数字英文字母时的排版不齐问题
* @param tv 被排版的TextView
* @return
*/
public static String autoSplitText(final TextView tv){
final String rawText=tv.getText().toString(); //原始文本
final Paint tvPaint=tv.getPaint(); //paint,包含字体等信息
final float tvWidth=tv.getWidth()-tv.getPaddingLeft()-tv.getPaddingRight(); //控件可用宽度
//将原始文本按行拆分
String[]rawTextLines=rawText.replaceAll("\r","").split("\n");
StringBuilder sbNewText=new StringBuilder();
for(String rawTextLine:rawTextLines){
if(tvPaint.measureText(rawTextLine)<=tvWidth){
//如果整行宽度在控件可用宽度之内,就不处理了
sbNewText.append(rawTextLine);
}else{
//如果整行宽度超过控件可用宽度,则按字符测量,在超过可用宽度的前一个字符处手动换行
float lineWidth=0;
int count = 0;
for(int cnt=0;cnt!=rawTextLine.length();++cnt){
char ch=rawTextLine.charAt(cnt);
lineWidth+=tvPaint.measureText(String.valueOf(ch));
if(lineWidth<=tvWidth){
sbNewText.append(ch);
}else {
sbNewText.append("\n");
lineWidth = 0;
--cnt;
}
}
}
sbNewText.append("\n");
}
//把结尾多余的\n去掉
if(!rawText.endsWith("\n")){
sbNewText.deleteCharAt(sbNewText.length()-1);
}
return sbNewText.toString();
}
方法二(自定义View):
/**
-
Desc:文字排版整齐的TextView
/
public class AutoTextView extends View {
/*- 水平居中
/
private static final int CENTER_HORIZONTAL = 1;
/* - 垂直居中
/
private static final int CENTER_VERTICAL = 2;
/* - 居中(水平且垂直)
*/
private static final int CENTER = 3;
private static final String TAG = JeejioTextView.class.getSimpleName();
/**
- 字体大小
/
private int mTextSize;
/* - 字体颜色
/
private int mTextColor;
/* - 文本内容
/
private String mTextContent;
/* - 行间距
/
private int mLineSpace;
/* - 最大行数
/
private int mMaxLines;
/* - 画笔
/
private Paint mPaint;
private Paint.FontMetricsInt mTextFM;
/* - 行高
/
private int mSignleLineHeight;
/* - 屏幕高度
*/
private int mScreenHeght;
private int mScreenWidth;
/**- 当前内容宽度
/
private int mViewWidth;
/* - 当前内容高度
/
private int mViewHeight;
/* - 视图最小高度
/
private int mMinHeight;
/* - 视图最小宽度
/
private int mMinWidth;
/* - 视图最大宽度
/
private int mMaxWidth;
/* - 视图最大高度
/
private int mMaxHeight;
/* - 内容布局居中
*/
private int mGravity;
/**
- 文本行数
*/
private int mLineCount;
- 水平居中
public JeejioTextView(Context context) {
this(context, null);
}
public JeejioTextView(Context context, AttributeSet attrs) {
this(context, attrs, -1);
}
public JeejioTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
initPaint();
}
private void initPaint() {
if (mPaint == null) {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
mPaint.setTextSize(mTextSize);
mPaint.setStrokeWidth(1);
mPaint.setColor(mTextColor);
mPaint.setTextAlign(Paint.Align.LEFT);
mTextFM = mPaint.getFontMetricsInt();
mSignleLineHeight = Math.abs(mTextFM.top - mTextFM.bottom);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
mScreenWidth = displayMetrics.widthPixels;
mScreenHeght = displayMetrics.heightPixels;
}
private void init(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.JeejioTextView);
mTextSize = typedArray.getDimensionPixelSize(R.styleable.JeejioTextView_textSize, (int) sp2px(context, 16));
mMaxWidth = typedArray.getDimensionPixelSize(R.styleable.JeejioTextView_maxWidth, 0);
mGravity = typedArray.getInteger(R.styleable.JeejioTextView_gravity, 0);
mMaxHeight = typedArray.getDimensionPixelSize(R.styleable.JeejioTextView_maxHeight, 0);
mMinHeight = typedArray.getDimensionPixelSize(R.styleable.JeejioTextView_minHeight, 0);
mMinWidth = typedArray.getDimensionPixelSize(R.styleable.JeejioTextView_minWidth, 0);
mTextColor = typedArray.getColor(R.styleable.JeejioTextView_myTextColor, Color.BLACK);
mTextContent = typedArray.getString(R.styleable.JeejioTextView_myText);
mLineSpace = typedArray.getDimensionPixelSize(R.styleable.JeejioTextView_lineSpace, 0);
mMaxLines = typedArray.getInteger(R.styleable.JeejioTextView_maxLine, 0);
typedArray.recycle();
}
/**
* sp -> px 将sp转换为px
*
* @param context
* @param sp
* @return
*/
private float sp2px(Context context, int sp) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.getResources().getDisplayMetrics());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mViewWidth = getViewWidth(widthMeasureSpec);
mViewHeight = getViewHeight(heightMeasureSpec);
setMeasuredDimension(mViewWidth, mViewHeight);
}
/**
* Date: 2020/1/4 15:18
* Desc:通过父容器以及自身高度 确定最终高度
*/
private int getViewHeight(int heightMeasureSpec) {
if (TextUtils.isEmpty(mTextContent)) {
return 0;
}
int height = 0;
int size = MeasureSpec.getSize(heightMeasureSpec);
int mode = MeasureSpec.getMode(heightMeasureSpec);
switch (mode) {
case MeasureSpec.EXACTLY:
height = size;
getRealHeight();
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.UNSPECIFIED:
if (!TextUtils.isEmpty(mTextContent)) {
height = (int) getRealHeight();
}
break;
}
// 如果存在最小高度
if (mMinHeight != 0 && height < mMinHeight) {
height = mMinHeight;
}
// 如果存在最大高度
if (mMaxHeight != 0 && height > mMaxHeight) {
height = mMaxHeight;
}
return height;
}
/**
* Date: 2020/1/4 15:17
* Desc:获取视图高度
*/
private float getRealHeight() {
String[] split = mTextContent.split("\n");
int count = 0;
for (int i = 0; i < split.length; i++) {
String text = split[i];
float textWidth = mPaint.measureText(text, 0, text.length());
float temCount = textWidth * 1.0f / (getMaxContentWidth());
if (temCount >= 1) {
count = (int) (count + Math.ceil(temCount));
} else {
count++;
}
}
if (mMaxLines != 0 && count > mMaxLines) {
count = mMaxLines;
}
mLineCount = count;
return count * mSignleLineHeight + mLineSpace * (count - 1) + getPaddingBottom() + getPaddingTop();
}
/**
* Date: 2020/1/4 15:16
* Desc:通过父容器以及自身宽度 确定最终宽度
*/
private int getViewWidth(int widthMeasureSpec) {
if (TextUtils.isEmpty(mTextContent)) {
return 0;
}
int width = 0;
int size = MeasureSpec.getSize(widthMeasureSpec);
int mode = MeasureSpec.getMode(widthMeasureSpec);
switch (mode) {
case MeasureSpec.EXACTLY:
width = size;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.UNSPECIFIED:
if (!TextUtils.isEmpty(mTextContent)) {
width = getRealWidth() + getPaddingLeft() + getPaddingRight();
}
break;
}
// 如果存在最小宽度
if (mMinWidth != 0 && width < mMinWidth) {
width = mMinWidth;
}
// 如果存在最大宽度
if (mMaxWidth != 0 && width > mMaxWidth) {
width = mMaxWidth;
}
return width;
}
/**
* Date: 2020/1/4 15:16
* Desc:获取视图高度
*/
private int getRealWidth() {
int width = 0;
String[] split = mTextContent.split("\n");
for (int i = 0; i < split.length; i++) {
String text = split[i];
float textWidth = mPaint.measureText(text, 0, text.length());
width = (int) Math.max(width, textWidth);
}
if (width > mScreenWidth - getPaddingRight() - getPaddingLeft()) {
width = mScreenWidth - getPaddingRight() - getPaddingLeft();
}
return width;
}
/**
* Date: 2020/3/16 14:51
* Desc:获取内容最大宽度
*/
private int getMaxContentWidth() {
int maxWidth = 0;
float contentWidth = mViewWidth - getPaddingRight() - getPaddingLeft();
String[] split = mTextContent.split("\n");
for (int i = 0; i < split.length; i++) {
String text = split[i];
if (TextUtils.isEmpty(text)) {
continue;
}
float textWidth = mPaint.measureText(text, 0, text.length());
int line = (int) Math.ceil(textWidth * 1.0f / (contentWidth));
for (int j = 0; j < line; j++) {
String subText = getTextByIndex(text, (int) contentWidth);
float subtextWidth = mPaint.measureText(subText, 0, subText.length());
maxWidth = (int) Math.max(subtextWidth, maxWidth);
text = text.substring(subText.length());
}
}
return maxWidth;
}
@Override
protected void onDraw(Canvas canvas) {
if (mTextContent != null && mTextContent.length() > 0) {
initPaint();
float startL = 0.0f;
float startT = 0.0f;
float contentHeight = getRealHeight();
float contentWidth = mViewWidth - getPaddingRight() - getPaddingLeft();
int maxContentWidth = getMaxContentWidth();
startL += getPaddingLeft();
int textTop = mSignleLineHeight / 2 + (mTextFM.bottom - mTextFM.top) / 2 - mTextFM.bottom;
startT += getPaddingTop() + textTop;
String[] split = mTextContent.split("\n");
for (int i = 0; i < split.length; i++) {
String text = split[i];
if (TextUtils.isEmpty(text)) {
startT += mSignleLineHeight + mLineSpace;
continue;
}
float textWidth = mPaint.measureText(text, 0, text.length());
int line = (int) Math.ceil(textWidth * 1.0f / maxContentWidth);
for (int j = 0; j < line; j++) {
String subText = getTextByIndex(text, (int) contentWidth);
float subtextWidth = mPaint.measureText(subText, 0, subText.length());
if (i == 0 && j == 0) {
if (split.length + line - 1 > 1) {
switch (mGravity) {
// 水平居中
case CENTER_HORIZONTAL:
if (contentWidth - subtextWidth > 0) {
startL = mViewWidth / 2 - maxContentWidth / 2;
}
break;
// 垂直居中
case CENTER_VERTICAL:
if (contentHeight > 0 && contentHeight < mViewHeight) {
startT = (mViewHeight / 2 - contentHeight / 2) + textTop;
}
break;
// 居中
case CENTER:
if (contentHeight > 0 && contentHeight < mViewHeight) {
startT = (mViewHeight / 2 - contentHeight / 2) + textTop;
}
if (contentWidth - subtextWidth > 0) {
startL = mViewWidth / 2 - maxContentWidth / 2;
}
break;
}
} else {
switch (mGravity) {
// 水平居中
case CENTER_HORIZONTAL:
startL = mViewWidth / 2 - subtextWidth / 2;
break;
// 垂直居中
case CENTER_VERTICAL:
startT = mViewHeight / 2 - mSignleLineHeight / 2 + textTop;
break;
// 居中
case CENTER:
startL = mViewWidth / 2 - subtextWidth / 2;
startT = mViewHeight / 2 - mSignleLineHeight / 2 + textTop;
break;
}
}
}
canvas.drawText(subText, startL, startT, mPaint);
text = text.substring(subText.length());
startT += mSignleLineHeight + mLineSpace;
}
}
}
}
private String getTextByIndex(String text, int mMaxWidth) {
int start = 0;
int end = text.length();
int middle;
String curText = "";
boolean error = false;
while (start <= end) {
middle = (start + end) / 2;
String substring = text.substring(0, middle);
curText = substring;
float substringWidth = mPaint.measureText(substring, 0, substring.length());
if (substringWidth > mMaxWidth) {
end = middle - 1;
error = true;
} else if (substringWidth < mMaxWidth) {
start = middle + 1;
error = false;
} else {
error = false;
break;
}
}
if (error) {
curText = curText.substring(0, curText.length() - 1);
}
return curText;
}
/**
* Date: 2020/1/4 15:17
* Desc:设置字体大小
*/
public void setTextSize(int textSize) {
setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
}
/**
* Date: 2020/2/17 17:07
* Desc:设置字体大小
*
* @param unit 转换类型
* @param size 字体大小
*/
public void setTextSize(int unit, int size) {
this.mTextSize = (int) TypedValue.applyDimension(unit, size, getResources().getDisplayMetrics());
initPaint();
requestLayout();
invalidate();
}
/**
* Date: 2020/1/4 15:17
* Desc:设置字体颜色
*/
public void setTextColor(int textColor) {
this.mTextColor = textColor;
invalidate();
}
/**
* Date: 2020/1/4 15:17
* Desc:设置文本
*/
public void setText(String textContent) {
this.mTextContent = textContent;
requestLayout();
invalidate();
}
/**
* Date: 2020/1/6 13:53
* Desc:获取当前文本
*/
public CharSequence getText() {
return mTextContent;
}
/**
* Date: 2020/2/17 17:11
* Desc:获取文本行数
*/
public int getLineCount() {
return mLineCount;
}
/**
* Date: 2020/2/18 13:43
* Desc:获取字体大小
*/
public float getTextSize() {
return mTextSize;
}
}
网友评论