Я хочу, чтобы TextView корректировал размер шрифта, чтобы текст в представлении автоматически расширялся (или уменьшался), чтобы заполнить всю ширину представления. Я думал, что смогу сделать это, создав настраиваемый TextView, который переопределяет onDraw() следующим образом:
public class MaximisedTextView extends TextView {
// (calls to super constructors here...)
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
TextPaint textPaint = this.getPaint();
Rect bounds = new Rect();
String text = (String)this.getText(); // current text in view
float textSize = this.getTextSize(); // current font size
int viewWidth = this.getWidth() - this.getPaddingLeft() - this.getPaddingRight();
textPaint.getTextBounds(text, 0, text.length(), bounds);
int textWidth = bounds.width();
// reset font size to make text fill full width of this view
this.setTextSize(textSize * viewWidth/textWidth);
}
}
Тем не менее, это отправляет приложение в бесконечный цикл (при этом размер шрифта растет и уменьшается каждый раз!), поэтому я явно об этом не так. Вызывает ли вызов setTextSize() действие invalidate, так что onDraw вызывается снова, бесконечно?
Есть ли способ предотвратить рекурсивный вызов (если это происходит)? Или я должен идти об этом совершенно по-другому?
Вызывается вызов setTextSize() invalidate, так что onDraw вызывается снова, бесконечно?
Да, возможно, что происходит. Если вы посмотрите исходный код setTextSize
, вы увидите, что он вызовет этот метод:
private void setRawTextSize(float size) {
if (size != mTextPaint.getTextSize()) {
mTextPaint.setTextSize(size);
if (mLayout != null) {
nullLayouts();
requestLayout();
invalidate(); // yeahh... invalidate XD
}
}
}
Итак, если вы выполняете тяжелую работу по переопределению метода onDraw
, почему бы вам не использовать непосредственно некоторые из drawText
методов Canvas
class?
Это фантастика! Престижность! Я все еще приспосабливаюсь к этому чудесному миру, в котором мы живем, где мы можем просто посмотреть исходный код, чтобы узнать, что происходит...
В интересах любого, кто может быть заинтересован, я использовал ярлык метода TextPaint.setTextSize() вместо того, чтобы вникать в Canvas.drawText(), поэтому мой onDraw() теперь выглядит следующим образом:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
TextPaint textPaint = this.getPaint();
Rect bounds = new Rect();
String text = (String)this.getText();
float textSize = this.getTextSize();
int viewWidth = this.getWidth() - this.getPaddingLeft() - this.getPaddingRight();
textPaint.getTextBounds(text, 0, text.length(), bounds);
int textWidth = bounds.width();
float newTextSize = (float)Math.floor(textSize * viewWidth/textWidth);
// note: adapted from TextView.setTextSize(), removing invalidate() call:
// get the raw text size...
Context c = getContext();
Resources r = c==null ? Resources.getSystem() : c.getResources();
int unit = TypedValue.COMPLEX_UNIT_SP;
float rawSize = TypedValue.applyDimension(unit, newTextSize, r.getDisplayMetrics());
// ... and apply it directly to the TextPaint
textPaint.setTextSize(rawSize);
}
... и это работает. Спасибо!