在画布上绘制自定义大小文本

时间:2017-12-13 03:09:49

标签: android android-canvas textview android-vectordrawable

我需要在画布上绘制一些文字。我已经在画布中添加了一个矩形框,我的目标是使这个文本适合框,但无论我尝试什么,文本永远不适合所有屏幕尺寸。

另一件事是这个文本是简单的HTML。

TextView currDateLabel = new TextView(getContext());
currDateLabel.layout(0, 0, boxSize.x, boxSize.y);
currDateLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.label_date));
currDateLabel.setTextColor(Color.WHITE);
currDateLabel.setText(Html.fromHtml("Dec 11<sup><small><small>TH</small></small></sup>"));
currDateLabel.setDrawingCacheEnabled(true);

Bitmap dateBitmap = currDateLabel.getDrawingCache(true);
// I've also tried setting the width of this Bitmap but it doesn't seem to do anything

this.canvas.drawBitmap(dateBitmap, boxPosition.x, boxPosition.y, null);

所以在这里解释一些变量:

  • boxSize是一个Point对象,用于存储画布上框的宽度和高度。 这些值似乎对TextView的大小没有影响,因为我可以看到文字超出了框。

  • boxPosition是一个Point对象,用于在画布上存储该框的xy位置。

  • R.dimen.label_datedimens.xml个文件中的值。

我创建了多个dimens.xml个文件(values/dimens.xmlvalues-hdpi/dimens.xmlvalues-xhdpi/dimens.xml等等)

我以为我可以测试大多数屏幕尺寸,并计算每个屏幕类别的文字大小。但是它没有按照我的预期工作。

这些值适用于 Samsung Galaxy S8

  

屏幕宽度:1440,屏幕高度:2768
  屏幕密度:4.0
  屏幕密度DPI:640
  屏幕缩放密度:4.0

这些值适用于 Samsung Galaxy S7

  

屏幕宽度:1440,屏幕高度:2560
  屏幕密度:4.0
  屏幕密度DPI:640
  屏幕缩放密度:4.0

它们都属于XXXHDPI类别,因此它们具有相同的字体大小,但Galaxy S8文本适合框,而Galaxy S7文本太大而且不在框内。

我在这里错过了什么吗?

在Canvas上绘制HTML文本有什么完全不同的方法吗?

=============================================== ===

编辑:

更详细地解释我的用例:

我指的是一个SVG / Vector对象。

label_down.xml

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="90dp"
    android:height="45dp"
    android:viewportWidth="90"
    android:viewportHeight="45">

    <path
        android:fillColor="?attr/labelColor"
        android:pathData="M 0 0 L 0 37.532 L 36.63 37.532 L 45 45 L 53.371 37.532 L 90 37.532 L 90 0 Z" />
</vector>

然后我从该向量创建一个Bitamp对象,并在Canvas上绘制Bitmap

VectorDrawableCompat vectorDrawableCompat = VectorDrawableCompat.create(getContext().getResources(), R.drawable.label_down, theme);
Bitmap bitmap = Bitmap.createBitmap(vectorDrawableCompat.getIntrinsicWidth(), vectorDrawableCompat.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
this.canvas.drawBitmap(bitmap, someXPos, someYPos, null);

这样做会产生以下结果:

enter image description here

现在,我的目标是在该框内创建文本。

希望这更有意义。

2 个答案:

答案 0 :(得分:1)

我认为这指出了“sp”和“dp”单位之间的差异。您没有在问题中记录维度文件中Template.instance().editType.set(false); Template.instance().editZip.set(!template.editZip.get()); Template.instance().editHeadCount.set(false); Template.instance().editDate.set(false); Template.instance().editTime.set(false) ; Template.instance().editDuration.set(false); 的值。我假设,因为它是一个文本大小的单位,你使用“sp”单位。

如果是这样,请将“xxsp”更改为“xxdp”以检查是否有差异。我刚刚在Nexus 5X API 26仿真器和运行Android 7.0的Galaxy S7上试用了这个,而“dp”单元修复了HTML文本的问题。这就是我所看到的:

Nexus 5X API 26仿真器

enter image description here

Galaxy S7 Device API Android 7.0

enter image description here

更新:我很好奇究竟发生了什么。在S7设置中,可缩放像素(SP)的缩放系数看起来大于1。转到“设置 - &gt;显示 - &gt;屏幕缩放和字体”,并将“FONT SIZE”设置为第三个哈希标记。你的文字现在可以正确显示。

您不希望文本独立于图形进行缩放,因此,IMO使用与密度无关的像素(DP)作为文本的单位,这是保持图形和文本之间一致性的正确方法。

第二次更新:对于给定的屏幕尺寸/密度,只要图形的大小固定并且显示的字体大小可以根据设备设置而改变,您将继续有可能文本不适合。如果您不认为将与密度无关的像素指定为字体的单位,则可以继续使用可缩放像素,但调整代码中使用的字体大小。像这样:

function turnOffSelect(currentDiv) {
    var divArray = ['.editType', '.editZip', '.editHeadCount', '.editDate', '.editTime', '.editDuration' ]  
    for (i = 0; i < divArray.length; i++) {
        if (divArray[i] != currentDiv) {
            Template.instance().eval(divArray[i]).set(false);           
        }
    }
}

这会将字体的有效缩放系数调整回1.0。这里的缺点是虽然你可能会说,label_date字体大小,但实际显示的大小会有所不同,并且会小于同样为float fontScale = getResources().getConfiguration().fontScale; textview.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources() .getDimensionPixelSize(R.dimen.label_date_sp) / fontScale); 的其他元素。这与指定“DP”具有相同的效果,但将使用更标准的“SP”单位。

答案 1 :(得分:0)

HTML文本无法正常呈现,我建议将DOM对象绘制到画布中

DOM Elements on Canvas