Текст текстового текста Android обрезается по сторонам пользовательским шрифтом
Это то, что происходит в режиме предварительного просмотра и на устройстве:
![Текстовая ошибка]()
TextView ничего особенного, он просто загружает пользовательский шрифт:
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>
Как вы можете видеть, левые части, такие как "j" и "f", обрезаны.
Настройка отступов или полей не работает.
Этот шрифт вписывается в кадр при использовании из других программ.
Спасибо заранее.
Изменить:
То, о чем упоминается @play_err_, не является решением в моем случае.
Ответы
Ответ 1
Этот ответ привел меня к правильному пути:
fooobar.com/questions/402490/...
Итак, решение заключается в создании пользовательского 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());
}
}
Ответ 2
Я столкнулся с той же проблемой, когда использовал некоторые шрифты в EditText
.
Моей первой попыткой было использовать отступы. Размер просмотра увеличился, но текст все еще обрезан.
![enter image description here]()
Затем я посмотрел на исходный код TextView
. В методе onDraw
метод Canvas.clipRect
для выполнения этой обрезки.
![enter image description here]()
Мое решение обойти обрезку при использовании заполнения:
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 TextView {
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);
}
}
![enter image description here]()
Ответ 3
android:gravity="center"
или использовать
android:layout_paddingleft="value"
надеюсь, что это будет работать..
Ответ 4
Что делать, если вы оберните его в другой макет и добавьте к нему дополнение? Например, что-то вроде этого:
<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>
Не имея шрифта и других тем и т.д. Я только что попробовал его с помощью курсорного шрифта, например, и на моей машине это выглядело бы так.
скриншот
Обновление:
Похоже, вы не единственный, у кого была эта проблема, а остальные ответы здесь и здесь и к сожалению, относятся к добавлению дополнительных пробелов.
Я создал биг-код ошибки здесь, поскольку он выглядит как ошибка для меня.
Ответ 5
Обходной путь - добавить пробел перед вводом. Это сэкономит вам много кода, но приведет к "отступу" слева.
android:text=" text after a space"
Ответ 6
Переработано решение @Dmitry Kopytov:
- в Котлине
- переработать старый растровое изображение
- добавлена документация
- откатитесь на рендеринг TextView по умолчанию, если растровое изображение не может быть создано (недостаточно памяти)
Код:
/**
* This TextView is able to draw text on the padding area.
* It 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
}
}