自定义View时,如何设置字体的大小和间距,和XML布局达到一样的效果

问题

1、我们再Android布局的时候会涉及到不同分辨率的手机显示效果不同。

2、如果我们一律用XML布局,字体用SP,间距用DP,可以很好地显示TextView。

3、如果我们一律用自定义的布局,设置好mTextSize,mSpaceHeight,也可以显示TextView

4、但是如果我们要求自定义的布局,Paint画出来的字体和XML文件设置的效果是一样的,如何做到?

解决

<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:layout_gravity="center">
        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="0"
            android:layout_marginTop="-5dp"
            android:textColor="@color/c_ffffff"
            android:textSize="45sp" />

        <TextView
            android:id="@+id/text_status"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text=""
            android:layout_marginTop="-6dp"
            android:textColor="@color/c_ffffff"
            android:textSize="12sp"/>
LinearLayout>

根据上面的布局文件,可以发现两个TextView,第一个字体45SP,第二个字体12SP,上下距离-6dp。效果如图所示:

自定义View时,如何设置字体的大小和间距,和XML布局达到一样的效果_第1张图片

现在我们要求在定义布局中,用Paint画出这样的效果。

首先我们看一张图:

自定义View时,如何设置字体的大小和间距,和XML布局达到一样的效果_第2张图片

这张图标记了很多高度,但我们需要关注的只有3个

  • 1、Baseline,基准点是baseline
  • 2、Accent,Ascent是baseline之上至字符最高处的距离
  • 3、Descent,Descent是baseline之下至字符最低处的距离

我们要用画笔画的效果如图所示:

自定义View时,如何设置字体的大小和间距,和XML布局达到一样的效果_第3张图片

可以看出此时字体大小,甚至两个TextView之间高度和前面XML布局的效果都有很大的差异,现在我们要求大字体在圆圈的中间,小字体距离大字体-6dp。

本文只关注字体的设置,其他不论。

String str = nums;
mPaint.setColor(mTextColor);
mPaint.setTextSize(mTextSize);
mPaint.setStyle(Style.FILL);

float textWidth = mPaint.measureText(str);
Paint.FontMetrics metric = mPaint.getFontMetrics();
float baseline = getHeight() / 2 - (metric.ascent + metric.descent) / 2;
canvas.drawText(str, getWidth() / 2 - textWidth / 2, baseline, mPaint);

mPaint.setTextSize(mSmallTextSize);
String strstatus = mStatus;
canvas.drawText(strstatus, (getWidth()-mPaint.measureText(strstatus)) / 2, baseline+spaceH+((metric.descent-metric.ascent))/2, mPaint);

首先在设置mTextSize和mSmallTextSize的时候要注意,一定要把sp转换px。

(最初的时候,我把UI设计师标注的px直接设置进来,导致在分辨率低的手机上太难看)

画第一个Text的时候,位置为总高度的中间位置,我们获取字体的metric ,得到ascent 和descent,求得字体的baseline高度。(descent为正数,ascent为负数)
其次在画第二个Text的时候,切记位置为,第一个Text的高度+Space高度。高度必须把dp转换为px

mTextSize = sp2px(context,45);
mSmallTextSize = sp2px(context,12);
spaceH = dip2px(context,-6);

转换代码如下:

1、sp转px

public static int sp2px(Context context, float spValue) {
   final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
   return (int) (spValue * fontScale + 0.5f);
}

2、dp转px

public static int dip2px(Context context, float dipValue) {
    final float scale = context.getResources().getDisplayMetrics().density;
    return (int) (dipValue * scale + 0.5f);
}

这样就达到了和XML布局一样的效果,即使在分辨率低的手机上也是一样。
如图效果:

XML布局
自定义View时,如何设置字体的大小和间距,和XML布局达到一样的效果_第4张图片

自定义View
自定义View时,如何设置字体的大小和间距,和XML布局达到一样的效果_第5张图片

你可能感兴趣的:(Android经验)