由于textview在绘制文字时,是按照四格线为基准绘制的,所以会在实际显示文字的时候,在textview内部显示出默认的内边距,该内边距并不是padding造成的。具体情况请参考:http://blog.csdn.net/harvic880925/article/details/50423762
网上也有不少解决方案例如:
android:includeFontPadding=
"false";
android:lineSpacingMultiplier=
"0.9"
等等,都没达到我想要的预期要求,所以在参考了 http://blog.csdn.net/Ab0510/article/details/52219464之后,
写了个自定义TextView达到要求。
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MyTextView extends LinearLayout {
private MyTextViewInner textView;
public MyTextView(Context context) {
super(context);
init(null, 0);
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, 0);
}
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs, defStyle);
}
private void init(AttributeSet attrs, int defStyleAttr) {
if (attrs != null && defStyleAttr > 0) {
textView = new MyTextViewInner(getContext(), attrs, defStyleAttr);
} else if (attrs != null) {
textView = new MyTextViewInner(getContext(), attrs);
} else {
textView = new MyTextViewInner(getContext());
}
this.setPadding(0, 0, 0, 0);
addView(textView);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
width = width + textView.getPaddingLeft() + textView.getPaddingRight();
setMeasuredDimension(width, getMeasuredHeight());
}
public TextView getTextView() {
return textView;
}
public class MyTextViewInner extends android.support.v7.widget.AppCompatTextView {
//设置是否remove间距,true为remove
private boolean noDefaultPadding = true;
private Paint.FontMetricsInt fontMetricsInt;
private Rect minRect;
public MyTextViewInner(Context context) {
super(context);
}
public MyTextViewInner(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyTextViewInner(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (fontMetricsInt == null) {
//fontMetricsInt包含的是text文字四条线的 距离,
//此四条线距离也是以text文字baseline为基准的
fontMetricsInt = new Paint.FontMetricsInt();
}
getPaint().getFontMetricsInt(fontMetricsInt);
if (minRect == null) {
//minRect用来获取文字实际显示的时候的左上角和右下角 坐标
//该坐标是以text文字baseline为基准的
minRect = new Rect();
}
getPaint().getTextBounds(getText().toString(), 0, getText().length(), minRect);
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) this.getLayoutParams();
lp.topMargin = -(fontMetricsInt.bottom - minRect.bottom) + (fontMetricsInt.top - minRect.top);
lp.rightMargin = -(minRect.left + (getMeasuredWidth() - minRect.right));
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
if (noDefaultPadding) {
if (fontMetricsInt == null) {
//fontMetricsInt包含的是text文字四条线的 距离,
//此四条线距离也是以text文字baseline为基准的
fontMetricsInt = new Paint.FontMetricsInt();
}
getPaint().getFontMetricsInt(fontMetricsInt);
if (minRect == null) {
//minRect用来获取文字实际显示的时候的左上角和右下角 坐标
//该坐标是以text文字baseline为基准的
minRect = new Rect();
}
getPaint().getTextBounds(getText().toString(), 0, getText().length(), minRect);
canvas.translate(-minRect.left, fontMetricsInt.bottom - minRect.bottom);
}
super.onDraw(canvas);
}
@Override
public void setText(CharSequence text, BufferType type) {
super.setText(text, type);
this.requestLayout();
}
}
}
没使用canvas.translate(0, fontMetricsInt.bottom - fontMetricsInt.descent);
而使用canvas.translate(0, fontMetricsInt.bottom - minRect.bottom);
是因为文字实际显示的时候,文字最底部并不一定是fontMetricsInt.descent,但minRect.bottom确一定能取到实际显示的最底部的值。
具体原理还是要参考:http://blog.csdn.net/harvic880925/article/details/50423762
使用方法:
1.在xml中使用该自定义控件:
2.java代码中获取该控件,并操作该控件:
//myTextView实际上是自定义的LinearLayout
MyTextView myTextView = (MyTextView) findViewById(R.id.tv1);
//textView才是实际上的TextView
TextView textView = (TextView) myTextView.getTextView();
//对textView进行操作
textView.setText("perfect");
优点:1.去除了textView默认情况的下内边距;
2.支持textview原生的属性设置。
缺点:1.由于在原生textview外层嵌套了一层linearlayout,理论上会有性能降低,但是实际运行时候感觉不到;
2.也由于该层嵌套,所以在引用textview的时候需要多一步获取textview的方法调用。
上述缺点目前都是可接受的。
以后有机会优化上面的缺点。同时感谢上述引用网站的创作者。