Android textview文本使用自定义字体在侧面截断
这是预览和设备上发生的情况: TextView没有什么特别之处,它只是加载自定义字体:Android textview文本使用自定义字体在侧面截断,android,fonts,textview,Android,Fonts,Textview,这是预览和设备上发生的情况: TextView没有什么特别之处,它只是加载自定义字体: public class TestTextView extends AppCompatTextView { public TestTextView(Context context) { super(context); init(context); } public TestTextView(Context context, AttributeSe
public class TestTextView extends AppCompatTextView {
public TestTextView(Context context) {
super(context);
init(context);
}
public TestTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public TestTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
void init(Context context) {
Typeface t = Typeface.createFromAsset(context.getAssets(), "fonts/daisy.ttf");
setTypeface(t);
}
}
布局也很基本,但以防万一:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/material_red200"
android:orientation="vertical">
<*custompackage* .TestTextView
android:gravity="left"
android:padding="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="just some text for testing"
android:textColor="@color/material_black"
android:textSize="100dp" />
</LinearLayout>
如果您将其包装在另一个布局中并添加填充,会怎么样?例如,类似这样的事情:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="24dp">
<*custompackage* .TestTextView
android:gravity="left"
android:padding="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="just some text for testing"
android:textColor="@color/material_black"
android:textSize="100dp" />
</RelativeLayout>
没有你的字体和其他主题等,我只是尝试了草书字体,例如,在我的机器上,它会像这样。
更新:
看起来你不是唯一一个有这个问题和其他答案的人,不幸的是,这两个问题都与增加额外的空间有关
我创建了一个bug通知单,因为它在我看来像个bug。这个答案让我找到了正确的路径: 因此,解决方案是创建自定义Textview并重写onDraw方法:
@Override
protected void onDraw(Canvas canvas) {
final Paint paint = getPaint();
final int color = paint.getColor();
// Draw what you have to in transparent
// This has to be drawn, otherwise getting values from layout throws exceptions
setTextColor(Color.TRANSPARENT);
super.onDraw(canvas);
// setTextColor invalidates the view and causes an endless cycle
paint.setColor(color);
System.out.println("Drawing text info:");
Layout layout = getLayout();
String text = getText().toString();
for (int i = 0; i < layout.getLineCount(); i++) {
final int start = layout.getLineStart(i);
final int end = layout.getLineEnd(i);
String line = text.substring(start, end);
System.out.println("Line:\t" + line);
final float left = layout.getLineLeft(i);
final int baseLine = layout.getLineBaseline(i);
canvas.drawText(line,
left + getTotalPaddingLeft(),
// The text will not be clipped anymore
// You can add a padding here too, faster than string string concatenation
baseLine + getTotalPaddingTop(),
getPaint());
}
}
@覆盖
受保护的void onDraw(画布){
最终油漆=getPaint();
final int color=paint.getColor();
//用透明纸画你必须画的东西
//必须绘制此图,否则从布局中获取值会引发异常
setTextColor(颜色:透明);
super.onDraw(帆布);
//setTextColor使视图无效并导致无休止的循环
油漆。设置颜色(颜色);
System.out.println(“图纸文本信息:”);
Layout=getLayout();
字符串text=getText().toString();
对于(int i=0;i
我在EditText
中使用一些字体时遇到了同样的问题
我的第一次尝试是使用填充。视图大小增加,但文本仍被裁剪
然后我查看了源代码TextView
。在方法onDraw
中,调用方法Canvas.clipRect
执行此裁剪
我在使用填充时绕过裁剪的解决方案:
1) С创建从Canvas
继承的自定义类,并重写方法clipRect
public class NonClippableCanvas extends Canvas {
public NonClippableCanvas(@NonNull Bitmap bitmap) {
super(bitmap);
}
@Override
public boolean clipRect(float left, float top, float right, float bottom) {
return true;
}
}
2) 创建自定义TextView
并覆盖方法onSizeChanged
和onDraw
在方法onSizeChanged
中,创建位图和画布
在方法onDraw
中,通过将自定义的Canvas
传递给方法super.onDraw
来绘制位图。接下来,在目标画布上绘制此位图
public class CustomTextView extends AppCompatTextView {
private Bitmap _bitmap;
private NonClippableCanvas _canvas;
@Override
protected void onSizeChanged(final int width, final int height,
final int oldwidth, final int oldheight) {
if (width != oldwidth || height != oldheight) {
_bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
_canvas = new NonClippableCanvas(_bitmap);
}
super.onSizeChanged(width, height, oldwidth, oldheight);
}
@Override
protected void onDraw(Canvas canvas) {
_canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
super.onDraw(_canvas);
canvas.drawBitmap(_bitmap, 0, 0, null);
}
}
一种解决方法是在键入前添加空格。它将为您节省大量编码,但会导致左侧出现“填充”
android:text=“空格后的文本”
返工@Dmitry Kopytov解决方案:
- 在科特林
- 回收旧位图
- 添加文档
- 如果无法创建位图(内存不足),请使用默认的TextView渲染
我遇到了同样的问题,我使用
TextView.shadowLayer
为数千名非的人找到了一个一行解决方案
这是基于[Dmitry Kopytov]带来的源代码:
就是这样,现在
TextView.onDraw()
中的canvas.clipRect
不会切掉卷曲的字体边。将TextView.BufferType.SPANNABLE
替换为TextView.BufferType.NORMAL
尝试删除android:padding=“0dp”
@AlexanderTumanin这对结果没有任何影响。请尝试在最后一个字符后添加空格,或为TestTextView设置固定宽度。是否可以共享字体文件?是否应用了任何自定义的文本样式和边框?@AmitKumar这是我使用的字体:我想它仍然会被截断。看第一个字母“j”哦,我的错。一开始并没有注意到这一点。我只是假设这就是字体的风格。填充导致文本视图变小(正如预期的那样),对剪切没有任何影响。是的,在谷歌上搜索一下,人们对这个问题的唯一“修复”似乎是添加额外的空格。正如我在上面的回答中所提到的,我已经用谷歌创建了一个bug罚单(不确定他们是否会响应,但值得一试)。@Kai bug ticket是个好主意。我也很好奇他们是否会回应。这不是一个好主意。此解决方案可能仅适用于单行文本。如果有多行,您必须计算哪些文本进入哪行,并在前面添加空格(加上如果当前行的内容在空格后到达下一行,或者如果单词对于单行来说太长)。此外,一个空间可能不够。因此,这只适用于非常特殊的情况。另一种解决方案是将文本框的宽度增加几dps,并将文本放在中间。这可以在activityjava文件中完成。我需要输出1-3个符号,它们是从侧面剪下来的。我不想用重写类做任何复杂和通用的事情。添加空格解决了我的问题。当我使用它时,它可以工作,但如果我需要缩放文本视图,它会显示模糊。@lasnow确定它不会。这将覆盖整个绘图机制,然后仅使用数据提供新的渲染。您必须通过删除行setTextColor(Color.TRANSPARENT),为自己渲染光标代码>光标和
public class CustomTextView extends AppCompatTextView {
private Bitmap _bitmap;
private NonClippableCanvas _canvas;
@Override
protected void onSizeChanged(final int width, final int height,
final int oldwidth, final int oldheight) {
if (width != oldwidth || height != oldheight) {
_bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
_canvas = new NonClippableCanvas(_bitmap);
}
super.onSizeChanged(width, height, oldwidth, oldheight);
}
@Override
protected void onDraw(Canvas canvas) {
_canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
super.onDraw(_canvas);
canvas.drawBitmap(_bitmap, 0, 0, null);
}
}
/**
* This TextView is able to draw text on the padding area.
* It's mainly used to support italic texts in custom fonts that can go out of bounds.
* In this case, you've to set an horizontal padding (or just end padding).
*
* This implementation is doing a render-to-texture procedure, as such it consumes more RAM than a standard TextView,
* it uses an additional bitmap of the size of the view.
*/
class TextViewNoClipping(context: Context, attrs: AttributeSet?) : AppCompatTextView(context, attrs) {
private class NonClippableCanvas(@NonNull val bitmap: Bitmap) : Canvas(bitmap) {
override fun clipRect(left: Float, top: Float, right: Float, bottom: Float): Boolean {
return true
}
}
private var rttCanvas: NonClippableCanvas? = null
override fun onSizeChanged(width: Int, height: Int,
oldwidth: Int, oldheight: Int) {
if ((width != oldwidth || height != oldheight) && width > 0 && height > 0) {
rttCanvas?.bitmap?.recycle()
try {
Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)?.let {
rttCanvas = NonClippableCanvas(it)
}
} catch (t: Throwable) {
// If for some reasons the bitmap cannot be created, we fall back on default rendering (potentially cropping the text).
rttCanvas?.bitmap?.recycle()
rttCanvas = null
}
}
super.onSizeChanged(width, height, oldwidth, oldheight)
}
override fun onDraw(canvas: Canvas) {
rttCanvas?.let {
// Clear the RTT canvas from the previous font.
it.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
// Draw on the RTT canvas (-> bitmap) that will use clipping on the NonClippableCanvas, resulting in no-clipping
super.onDraw(it)
// Finally draw the bitmap that contains the rendered text (no clipping used here, will display on top of padding)
canvas.drawBitmap(it.bitmap, 0f, 0f, null)
} ?: super.onDraw(canvas) // If rtt is not available, use default rendering process
}
}
editTextOrTextView.setShadowLayer(editTextOrTextView.textSize, 0f, 0f, Color.TRANSPARENT)