Auto Scale TextView Text to Fit within Bounds
From June 2018 Android officially started supporting this feature for Android 4.0 (API level 14) and higher.
Check it out at: Autosizing TextViews
With Android 8.0 (API level 26) and higher:
<?xml version="1.0" encoding="utf-8"?>
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="12sp"
android:autoSizeMaxTextSize="100sp"
android:autoSizeStepGranularity="2sp" />
Programmatically:
setAutoSizeTextTypeUniformWithConfiguration(int autoSizeMinTextSize, int autoSizeMaxTextSize,
int autoSizeStepGranularity, int unit)
textView.setAutoSizeTextTypeUniformWithConfiguration(
1, 17, 1, TypedValue.COMPLEX_UNIT_DIP);
Android versions prior to Android 8.0 (API level 26):
<?xml version="1.0" encoding="utf-8"?>
<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">
<TextView
android:layout_width="match_parent"
android:layout_height="200dp"
app:autoSizeTextType="uniform"
app:autoSizeMinTextSize="12sp"
app:autoSizeMaxTextSize="100sp"
app:autoSizeStepGranularity="2sp" />
</LinearLayout>
Programmatically:
TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(
TextView textView, int autoSizeMinTextSize, int autoSizeMaxTextSize, int autoSizeStepGranularity, int unit)
TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(textView, 1, 17, 1,
TypedValue.COMPLEX_UNIT_DIP);
Attention: TextView must have layout_width="match_parent" or absolute size!
Increase the font size to fit height TextView Android
Actually, there's some trivial error. As You can seen, in your code there's checks for defaultTextSize
and so text font cannot get bigger than it, also there's correction of hi
is needed inside align loop, because it blocks searching sizes higher than defaultTextSize
.
So, final code which makes font big without limit would looks like the following:
public class FontFitTextView extends TextView {
// Attributes
private Paint mTestPaint;
/** 'Initial' text size */
private float mDefaultTextSize;
public FontFitTextView(final Context context) {
super(context);
initialize();
}
public FontFitTextView(final Context context, final AttributeSet attrs) {
super(context, attrs);
initialize();
}
private void initialize() {
mTestPaint = new Paint();
mTestPaint.set(this.getPaint());
mDefaultTextSize = getTextSize();
}
/*
* Re size the font so the specified text fits in the text box
* assuming the text box is the specified width.
*/
private void refitText(final String text, final int textWidth) {
if(textWidth <= 0 || text.isEmpty()) {
return;
}
int targetWidth = textWidth - this.getPaddingLeft() - this.getPaddingRight();
// this is most likely a non-relevant call
if(targetWidth <= 2) {
return;
}
// text already fits with the xml-defined font size?
mTestPaint.set(this.getPaint());
mTestPaint.setTextSize(mDefaultTextSize);
// adjust text size using binary search for efficiency
float hi = Math.max(mDefaultTextSize, targetWidth);
float lo = 2;
final float threshold = 0.5f; // How close we have to be
while (hi - lo > threshold) {
float size = (hi + lo) / 2;
mTestPaint.setTextSize(size);
if(mTestPaint.measureText(text) >= targetWidth) {
hi = size; // too big
} else {
lo = size; // too small
}
}
// Use lo so that we undershoot rather than overshoot
this.setTextSize(TypedValue.COMPLEX_UNIT_PX, lo);
}
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int height = getMeasuredHeight();
refitText(this.getText().toString(), parentWidth);
this.setMeasuredDimension(parentWidth, height);
}
@Override
protected void onTextChanged(final CharSequence text, final int start,
final int before, final int after) {
refitText(text.toString(), this.getWidth());
}
@Override
protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
if (w != oldw || h != oldh) {
refitText(this.getText().toString(), w);
}
}
}
You can test it with the following xml:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.TestApp.FontFitTextView
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/textView"
android:layout_centerInParent="true"
android:text="This text is to be resized." />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:id="@+id/minus_button"
android:text="-10px"
android:padding="20dp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@id/minus_button"
android:id="@+id/plus_button"
android:text="+10px"
android:padding="20dp" />
</RelativeLayout>
And activity:
public class MyActivity extends Activity {
private static final String TAG = "MyActivity";
TextView mTextView = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Show the layout with the test view
setContentView(R.layout.main);
mTextView = (TextView) findViewById(R.id.textView);
final Button buttonPlus = (Button) findViewById(R.id.plus_button);
buttonPlus.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
changeTextViewSize(10);
}
});
final Button buttonMinus = (Button) findViewById(R.id.minus_button);
buttonMinus.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
changeTextViewSize(-10);
}
});
}
/**
* Changes text size by needed delta
*
* @param delta in px
*/
private void changeTextViewSize(final int delta) {
final ViewGroup.LayoutParams params = mTextView.getLayoutParams();
params.height += delta;
params.width += delta;
mTextView.setLayoutParams(params);
}
}
Font size of TextView in Android application changes on changing font size from native settings
Actually, Settings font size affects only sizes in sp
. So all You need to do - define textSize
in dp
instead of sp
, then settings won't change text size in Your app.
Here's a link to the documentation: Dimensions
However please note that the expected behavior is that the fonts in all apps respect the user's preferences. There are many reasons a user might want to adjust the font sizes and some of them might even be medical - visually impaired users. Using dp
instead of sp
for text might lead to unwillingly discriminating against some of your app's users.
i.e:
android:textSize="32dp"
Scaling textSize in a TextView
Not that I am aware of, sorry.
Related Topics
How to Manually Include External Aar Package Using Gradle For Android
Multiple Dex Files Define Landroid/Support/V4/Accessibilityservice/Accessibilityserviceinfocompat
How to Hide the Title Bar For an Activity in Xml With Existing Custom Theme
Adding a Library/Jar to an Eclipse Android Project
Start Activity from Service in Android
Android, Detect When Other Apps Are Launched
Onactivityresult Method Is Deprecated, What Is the Alternative
"Arrayadapter Requires the Resource Id to Be a Textview" Xml Problems
Google Maps Android API V2 - Interactive Infowindow (Like in Original Android Google Maps)
Notification Not Showing in Oreo
Linear Layout and Weight in Android
Android Check Internet Connection
Communicating Between a Fragment and an Activity - Best Practices
Viewpager and Fragments - What's the Right Way to Store Fragment'S State
Android: Listview Elements With Multiple Clickable Buttons
Comparison of Android Networking Libraries: Okhttp, Retrofit, and Volley