上图第一个阿道夫:直接使用AppCompatTextView的展示效果
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="180dp"
android:layout_height="wrap_content"
android:layout_marginStart="100dp"
android:layout_marginTop="100dp"
android:background="@color/purple_200"
android:padding="0dp"
android:text="阿道夫"
android:textSize="20dp" />
第二个阿道夫:在第一个的基础上添加了 android:includeFontPadding=“false”,发现还是有一点留白。
第三个阿道夫:通过继承View后,自定义控件。
下面说下自定义控件如何实现上面三个阿道夫的效果
说一下我对上图的理解:
- FontMetricInt.top 和 FontMetricInt.bottom ------- 表示字体的顶部和底部,其会比字体实际更大些
- FontMetricInt.ascent 和 FontMetricInt.descent -------- 表示字体可能占据的顶部和底部。为啥说可能了?
可以看到上图的dangwen中的g的底部会比danwen都要底,其他字体可能比g的底部还要低。那么最低的底线就是FontMetricInt.descent. - Rect ------- 红框部分,表示字体实际需要的大小。也是第三个阿道夫想要的。
首先我们通过自定义View 来实现第一个阿道夫的效果
模拟第一个阿道夫
- 获得 fontMetrics 对象
。。。。。。
// 重写onMeasure 和 onDraw
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
calculateTextParams();
setMeasuredDimension(widthMeasureSpec, (int) (-fm.top + fm.bottom));
}
@Override
protected void onDraw(Canvas canvas) {
final String text = calculateTextParams();
canvas.save();
// -fm.top 就是基线位置
canvas.drawText(text, 0, -fm.top, mPaint);
canvas.restore();
}
private final Paint mPaint = new Paint();
private Paint.FontMetrics fm;
private String calculateTextParams() {
final String text = "阿道夫";
final int textLength = text.length();
mPaint.setTextSize(60);
fm = mPaint.getFontMetrics();
if (textLength == 0) {
mBounds.right = mBounds.left;
}
return text;
}
。。。。。。
效果图如下:
模拟第二个阿道夫
将上面的代码修改下:
setMeasuredDimension(widthMeasureSpec, (int) (-fm.top + fm.bottom));
canvas.drawText(text, 0, -fm.top, mPaint);
模拟第三个阿道夫
第三个阿道夫上下不需要留白,我们只需要获得Rect红框就行。
public class TextNoPaddingextends View {
private final static String TAG = "TextNoPadding";
private final Paint mPaint = new Paint();
private final Rect mBounds = new Rect();
public TestTextView(Context context) {
super(context);
}
public TestTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TestTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
final String text = calculateTextParams();
canvas.save();
canvas.drawText(text, 0, -mBounds.top, mPaint);
canvas.restore();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
calculateTextParams();
setMeasuredDimension(widthMeasureSpec, (int) (-mBounds.top + mBounds.bottom));
}
private String calculateTextParams() {
final String text = "阿道夫";
final int textLength = text.length();
mPaint.setTextSize(60);
mPaint.getTextBounds(text, 0, textLength, mBounds);
if (textLength == 0) {
mBounds.right = mBounds.left;
}
return text;
}
}
效果就是第三个阿道夫。。。。