I'm trying to create a method for resizing multi-line text in a TextView
such that it fits within the bounds (both the X and Y dimensions) of the TextView
.
At present, I have something, but all it does is resize the text such that just the first letter/character of the text fills the dimensions of the TextView
(i.e. only the first letter is viewable, and it's huge). I need it to fit all the lines of the text within the bounds of the TextView.
Here is what I have so far:
public static void autoScaleTextViewTextToHeight(TextView tv) { final float initSize = tv.getTextSize(); //get the width of the view's back image (unscaled).... float minViewHeight; if(tv.getBackground()!=null) { minViewHeight = tv.getBackground().getIntrinsicHeight(); } else { minViewHeight = 10f;//some min. } final float maxViewHeight = tv.getHeight() - (tv.getPaddingBottom()+tv.getPaddingTop())-12;// -12 just to be sure final String s = tv.getText().toString(); //System.out.println(""+tv.getPaddingTop()+"/"+tv.getPaddingBottom()); if(minViewHeight >0 && maxViewHeight >2) { Rect currentBounds = new Rect(); tv.getPaint().getTextBounds(s, 0, s.length(), currentBounds); //System.out.println(""+initSize); //System.out.println(""+maxViewHeight); //System.out.println(""+(currentBounds.height())); float resultingSize = 1; while(currentBounds.height() < maxViewHeight) { resultingSize ++; tv.setTextSize(resultingSize); tv.getPaint().getTextBounds(s, 0, s.length(), currentBounds); //System.out.println(""+(currentBounds.height()+tv.getPaddingBottom()+tv.getPaddingTop())); //System.out.println("Resulting: "+resultingSize); } if(currentBounds.height()>=maxViewHeight) { //just to be sure, reduce the value tv.setTextSize(resultingSize-1); } } }
I think the problem is in the use of tv.getPaint().getTextBounds(...)
. It always returns small numbers for the text bounds... small relative to the tv.getWidth()
and tv.getHeight()
values... even if the text size is far larger than the width or height of the TextView
.
To use preset sizes to set up the autosizing of TextView in XML, use the android namespace and set the following attributes: Set the autoSizeText attribute to either none or uniform. none is a default value and uniform lets TextView scale uniformly on horizontal and vertical axes.
setTextSize(float size) method to set the size of text. textView.
app:autoSizeMinTextSize=”10sp” using this attribute the TextView will be resized up to the size of 10sp and app:autoSizeStepGranularity=”2sp” using this attribute we are uniformly reducing the size of the TextView as 2sp when it goes out of the screen.
The AutofitTextView library from MavenCentral handles this nicely. The source hosted on Github(1k+ stars) at https://github.com/grantland/android-autofittextview
Add the following to your app/build.gradle
repositories { mavenCentral() } dependencies { implementation 'me.grantland:autofittextview:0.2.+' }
Enable any View extending TextView in code:
AutofitHelper.create(textView);
Enable any View extending TextView in XML:
<me.grantland.widget.AutofitLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" /> </me.grantland.widget.AutofitLayout>
Use the built in Widget in code or XML:
<me.grantland.widget.AutofitTextView android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" />
New since Android O:
https://developer.android.com/preview/features/autosizing-textview.html
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:autoSizeTextType="uniform" android:autoSizeMinTextSize="12sp" android:autoSizeMaxTextSize="100sp" android:autoSizeStepGranularity="2sp" />
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With