I\'m looking for an optimal way to resize wrapping text in a TextView
so that it will fit within its getHeight and getWidth bounds. I\'m not simply looking for
I started with Chase's solution, but had to adapt two things before it was working as expected on my device (Galaxy Nexus, Android 4.1):
using a copy of TextPaint for measuring layout The documentation for TextView.getPaint() states that it should be used read-only, so I made a copy in both places where we use the paint object for measuring:
// 1. in resizeText()
if (mAddEllipsis && targetTextSize == mMinTextSize && textHeight > height) {
// Draw using a static layout
// modified: use a copy of TextPaint for measuring
TextPaint paint = new TextPaint(textPaint);
// 2. in getTextHeight()
private int getTextHeight(CharSequence source, TextPaint originalPaint, int width, float textSize) {
// modified: make a copy of the original TextPaint object for measuring
// (apparently the object gets modified while measuring, see also the
// docs for TextView.getPaint() (which states to access it read-only)
TextPaint paint = new TextPaint(originalPaint);
// Update the text paint object
paint.setTextSize(textSize);
...
adding a unit to setting the text size
// modified: setting text size via this.setTextSize (instead of textPaint.setTextSize(targetTextSize))
setTextSize(TypedValue.COMPLEX_UNIT_PX, targetTextSize);
setLineSpacing(mSpacingAdd, mSpacingMult);
With these two modifications the solution is working perfectly for me, thanks Chase! I don't know whether it is due to Android 4.x that the original solution was not working. In case you want to see it in action or test whether it really works on your device, you can have a look at my flashcard app Flashcards ToGo where I use this solution to scale the text of a flashcard. The text can have arbitrary length, and the flashcards are displayed in different activities, sometimes smaller sometimes bigger, plus in landscape + portrait mode, and I haven't found any corner case where the solution would not work properly...