效果图:
上面的是原生Textview,第一行末尾数字整体换行了,
下面是自定义Textview,第一行末尾数字分别在第一行和第二行展示
布局中 MyTextview记得换成自己包名下的
<TextView
android:layout_margin="25dp"
android:id="@+id/test_tv"
android:lineSpacingExtra="8dp"
android:textSize="15sp"
android:textColor="#444444"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="文字文字文字文字文字文字文字文字文字1234567890字文字文字文字文字1234567890"
/>
<com.littlejie.app.panterdialog.MyTextView
android:layout_margin="25dp"
android:id="@+id/test_mytv"
android:lineSpacingExtra="8dp"
android:textSize="15sp"
android:textColor="#444444"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="文字文字文字文字文字文字文字文字文字1234567890字文字文字文字文字1234567890"
/>
自定义Textview: MyTextView类
public class MyTextView extends View {
//内容填充画笔
private Paint contentPaint;
//标准的字体颜色
private String contentNormalColor = "#737373";
//有焦点的字体颜色
private String contentFocuedColor = "#333333";
//控件宽度
private int viewWidth = 0;
//控件高度
private int viewHeight = 0;
//标准的字的样式
public static final int TEXT_TYPE_NORMAL = 1;
//控件获取焦点的时候进行的处理
public static final int TEXT_TYPE_FOCUED = 2;
//默认是标准的样式
private int currentTextType = TEXT_TYPE_NORMAL;
//默认当前的颜色
private String textColor = "#444444";
//字体大小
private int textSize = 60;
//内容
private String mText = "测试的文字信息";
//最小view高度
private float minHeight = 0;
//最小view宽度
private float minWidth = 0;
//行间距
private float lineSpace;
//最大行数
private int maxLines = 0;
//文字测量工具
private Paint.FontMetricsInt textFm;
///真实的行数
private int realLines;
//当前显示的行数
private int line;
//在末尾是否显示省略号
private boolean showEllipsise;
//文字显示区的宽度
private int textWidth;
//单行文字的高度
private int signleLineHeight;
private int mPaddingLeft,mPaddingRight,mPaddingTop,mPaddingBottom;
/**
* 省略号
**/
private String ellipsis = "...";
public MyTextView(Context context) {
this(context,null);
}
public MyTextView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttr(context,attrs);
init();
}
private boolean isFristload;
/**
* 初始化
*/
private void init() {
contentPaint = new Paint();
contentPaint.setTextSize(textSize);
contentPaint.setAntiAlias(true);
contentPaint.setStrokeWidth(2);
contentPaint.setColor(Color.parseColor(textColor));
contentPaint.setTextAlign(Paint.Align.LEFT);
textFm = contentPaint.getFontMetricsInt();
signleLineHeight=Math.abs(textFm.top-textFm.bottom);
}
/**
* 初始化属性
* @param context
* @param attrs
*/
private void initAttr(Context context,AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyTextView);
mPaddingLeft = typedArray.getDimensionPixelSize(R.styleable.MyTextView_paddingLeft, 0);
mPaddingRight = typedArray.getDimensionPixelSize(R.styleable.MyTextView_paddingRight, 0);
mPaddingTop = typedArray.getDimensionPixelSize(R.styleable.MyTextView_paddingTop, 0);
mPaddingBottom = typedArray.getDimensionPixelSize(R.styleable.MyTextView_paddingBottom, 0);
mText = typedArray.getString(R.styleable.MyTextView_text);
textColor = typedArray.getString(R.styleable.MyTextView_textColor);
if(textColor==null){
textColor="#444444";
}
// textSize = typedArray.getDimensionPixelSize(R.styleable.MyTextView_textSize, 60);
textSize = typedArray.getDimensionPixelSize(R.styleable.MyTextView_textSize, DensityUtil.sp2px(context,15));
lineSpace = typedArray.getInteger(R.styleable.MyTextView_lineSpacing, 20);
typedArray.recycle();
}
public void setText(String ss){
this.mText=ss;
invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
viewWidth=getMeasuredWidth();
textWidth=viewWidth-mPaddingLeft-mPaddingRight;
viewHeight= (int) getViewHeight();
setMeasuredDimension(viewWidth, viewHeight);
}
private float getViewHeight() {
char[] textChars=mText.toCharArray();
float ww=0.0f;
int count=0;
StringBuilder sb=new StringBuilder();
for(int i=0;i<textChars.length;i++){
float v = contentPaint.measureText(textChars[i] + "");
if(ww+v<=textWidth){
sb.append(textChars[i]);
ww+=v;
}
else{
count++;
sb=new StringBuilder();
ww=0.0f;
ww+=v;
sb.append(textChars[i]);
}
}
if(sb.toString().length()!=0){
count++;
}
return count*signleLineHeight+lineSpace*(count-1)+mPaddingBottom+mPaddingTop;
}
@Override
protected void onDraw(Canvas canvas) {
drawText(canvas);
}
/**
* 循环遍历画文字
* @param canvas
*/
private void drawText(Canvas canvas) {
char[] textChars=mText.toCharArray();
float ww=0.0f;
float startL=0.0f;
float startT=0.0f;
startL+=mPaddingLeft;
startT+=mPaddingTop+signleLineHeight/2+ (textFm.bottom-textFm.top)/2 - textFm.bottom;
StringBuilder sb=new StringBuilder();
for(int i=0;i<textChars.length;i++){
float v = contentPaint.measureText(textChars[i] + "");
if(ww+v<=textWidth){
sb.append(textChars[i]);
ww+=v;
}
else{
canvas.drawText(sb.toString(),startL,startT,contentPaint);
startT+=signleLineHeight+lineSpace;
sb=new StringBuilder();
ww=0.0f;
ww+=v;
sb.append(textChars[i]);
}
}
if(sb.toString().length()>0){
canvas.drawText(sb.toString(),startL,startT,contentPaint);
}
}
}
在 res-values下attr.xml中添加属性
<!--解决文字和数字换行不整齐-->
<declare-styleable name="MyTextView">
<attr name="paddingLeft" format="dimension" />
<attr name="paddingTop" format="dimension" />
<attr name="paddingRight" format="dimension" />
<attr name="paddingBottom" format="dimension" />
<attr name="textSize" format="dimension" />
<attr name="textColor" format="string" />
<attr name="text" format="string"/>
<attr name="lineSpacing" format="integer" />
<attr name="maxLine" format="integer"/>
<attr name="ellipsis" format="boolean" />
</declare-styleable>
Activity中
MyTextView testMyTv = findViewById(R.id.test_mytv);
String str = "文字文字文字文字文字文字文字文字文字1234567890字文字文字文字文字1234567890";
testMyTv.setText(str);