当我们使用TextView显示多行的文字或者单行时,为了美观,一般会加上行间距,这时就会用到lineSpacingExtra这个属性。
Android 5.0以下,在这个系统里面会添加一个行间距,导致多余空白。
Adnroid 5.0以上,google修复这个问题,但是由于厂商定制不一样,导致一些5.1版本的手机也会出现同样的问题,oppo等
解决思路:
1.需要理解一下字体属性及测量,先看一下https://blog.csdn.net/g0ose/article/details/80547461这一篇博客
2.那么从上面博客里面我们知道 , baseline,Descent这俩个属性
我们是否可以这样想一下,baseline + Descent + linespace? + paddingbottom = 组件最下面高度
3.自定义TextView
按上面思路,我们先继承一个AppCompatTextView,
public class LastLineSpaceTextView extends AppCompatTextView {
public LastLineSpaceTextView(Context context) {
this(context, null);
}
public LastLineSpaceTextView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public LastLineSpaceTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
我们需要到baseLine的高度,怎么去获取这个高度呢?看一下AppCompatTextView里面继承的TextView:
1. TextView有这个方法getLineBounds(int line, Rect bounds)
参数一:指定的行数的索引
参数二:传入一个rect实例,返回指定行的边框数据
返回值:所在行的baseline的y坐标
那么我们是不是可以知道了baseline的高度呢?看下面代码:
private Rect mLastLineRect;
private void init() {
mLastLineRect = new Rect();
}
int lastlineIndex = Math.min(getMaxLines(), getLineCount()) - 1;//获取最后一行的index
int baseline = getLineBounds(lastlineIndex, mLastLineRect);//获取到高度
其中getLineCount()获取的是实际行数(并不是指展示行数),getMaxLines()获取最大行数。
那么当最大行数小于实际行数,取最大行数
那么baseline拿到了,下一步获取Descent
Layout layout = getLayout();
layout.getPaint().getFontMetricsInt().descent
那么这样paddingbottom:getPaddingBottom()获取到了
那么linesspace:getLineSpacingExtra();
获取最下面高度:
mLastLineRect.bottom//就是bottom的高度
搭配完毕;下面开始撸代码了;
重点在于
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
下面我们需要设置高度:setMeasuredDimension(width,height);
需要的点在于height:重新设置高度
那么针对高度进行一个计算
import android.content.Context;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatTextView;
import android.text.Layout;
import android.util.AttributeSet;
public class LastLineSpaceTextView extends AppCompatTextView {
private Rect mLastLineRect;
private Rect mLastLineIndexRect;
public LastLineSpaceTextView(Context context) {
this(context, null);
}
public LastLineSpaceTextView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public LastLineSpaceTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mLastLineRect = new Rect();
mLastLineIndexRect = new Rect();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight() - calculateSpace());
}
private int calculateSpace() {
int result = 0;
//界面显示的最后一行的index
int lastlineIndex = Math.min(getMaxLines(), getLineCount()) - 1;
//获取实际的最后一行
int lastLineNomalIndex = getLineCount() - 1;
if (lastlineIndex >= 0) {
Layout layout = getLayout();
int baseline = getLineBounds(lastlineIndex, mLastLineRect);
getLineBounds(lastLineNomalIndex, mLastLineIndexRect);
int height = (mLastLineIndexRect.bottom - mLastLineRect.bottom);
if (getMeasuredHeight() == getLayout().getHeight() - height) {
if (getLineSpacingExtra() == 0) {
result = 0;
} else {
result = mLastLineRect.bottom - (baseline + layout.getPaint().getFontMetricsInt().descent + getPaddingBottom());
if (getLineSpacingExtra() > result) {
result = 0;
} else {
result = (int) getLineSpacingExtra();
}
}
}
}
return result;
}
}
代码如上:
直接使用这个TextView,属性设置就ok了
另外还有一种方式解决如这个博客:https://blog.csdn.net/etwge/article/details/72818859