Scale Text in a View to Fit

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!

Scale text in a view to fit?

You can use the TextUtils.EllipsizeCallback. When the text gets ellipsized this callback is done by the textview. Here you can set text size smaller than the current.

EDIT : Otherwise you can use TextUtils.ellipsize this way

while (mText != TextUtils.ellipsize(mText, textPaint, other params)) { 
textpaint.setTextSize(textpaint.getTextSize() - 1);
}

How to scale text to fit parent view with SwiftUI?

One can use GeometryReader in order to make it also work in landscape mode.

It first checks if the width or the height is smaller and then adjusts the font size according to the smaller of these.

GeometryReader{g in
ZStack {
Circle().strokeBorder(Color.red, lineWidth: 30)
Text("Text")
.font(.system(size: g.size.height > g.size.width ? g.size.width * 0.4: g.size.height * 0.4))
}
}

Sample Image
Sample Image

Font scaling based on size of container

If the container is not the body, CSS Tricks covers all of your options in Fitting Text to a Container.

If the container is the body, what you are looking for is Viewport-percentage lengths:

The viewport-percentage lengths are relative to the size of the initial containing block. When the height or width of the initial containing block is changed, they are scaled accordingly. However, when the value of overflow on the root element is auto, any scroll bars are assumed not to exist.

The values are:

  • vw (% of the viewport width)
  • vh (% of the viewport height)
  • vi (1% of the viewport size in the direction of the root element's inline axis)
  • vb (1% of the viewport size in the direction of the root element's block axis)
  • vmin (the smaller of vw or vh)
  • vmax (the larger or vw or vh)

1 v* is equal to 1% of the initial containing block.

Using it looks like this:

p {
font-size: 4vw;
}

As you can see, when the viewport width increases, so do the font-size, without needing to use media queries.

These values are a sizing unit, just like px or em, so they can be used to size other elements as well, such as width, margin, or padding.

Browser support is pretty good, but you'll likely need a fallback, such as:

p {
font-size: 16px;
font-size: 4vw;
}

Check out the support statistics: http://caniuse.com/#feat=viewport-units.

Also, check out CSS-Tricks for a broader look: Viewport Sized Typography

Here's a nice article about setting minimum/maximum sizes and exercising a bit more control over the sizes: Precise control over responsive typography

And here's an article about setting your size using calc() so that the text fills the viewport: http://codepen.io/CrocoDillon/pen/fBJxu

Also, please view this article, which uses a technique dubbed 'molten leading' to adjust the line-height as well. Molten Leading in CSS

SwiftUI scale text to fit the width and height

on UIKit minimumScaleFactor and minimumFontSize are ineffective unless you set adjustsFontSizeToFitWidth.

Instead of creating a VStack, you may want to place all the figures, separated by newlines, in a single text, and fit the text to the bounding rectangle.

With SwiftUI the solution looks like:

struct aView: View {
let array = [4, 5, 6]

var body: some View {
HStack(spacing: 100) {
Text(array.map {String($0)}.joined(separator: "\n"))
.font(.system(size: 1000))
.minimumScaleFactor(0.01)
.frame(width: 60, height: 300)
.border(Color.primary)
Text(array.map {String($0)}.joined(separator: "\n"))
.font(.system(size: 1000))
.minimumScaleFactor(0.01)
.frame(width: 30, height: 150)
.border(Color.primary)
}
}
}

How to scale the view to fit the content size in Android animation?

What you can do is ask the View to measure itself giving no constraint on its height. Please note the call to view.getWidth(), you can do that only after the View had been laid out, since you're calling it in onClick() it should be fine.

int widthSpec = View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY);
int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(widthSpec, heightSpec);
int targetHeight = view.getMeasuredHeight();

Assuming that your View is a TextView with these attributes set:

android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"

the full example would be

// this is the height measured with maxLines 1 and height
// to wrap_content
final int startHeight = view.getHeight();

// you want to measure the TextView with all text lines
view.setMaxLines(Integer.MAX_VALUE);

int widthSpec = View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY);
int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(widthSpec, heightSpec);

// final height of the TextView
int targetHeight = view.getMeasuredHeight();

// this is the value that will be animated from 0% to 100%
final int heightSpan = targetHeight-startHeight;

// remove that wrap_content and set the starting point
view.getLayoutParams().height = startHeight;
view.setLayoutParams(view.getLayoutParams());

Animation animation = new Animation(){
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
view.getLayoutParams().height = (int) (startHeight + heightSpan*interpolatedTime);
view.setLayoutParams(view.getLayoutParams());
}
};

animation.setDuration(1000);
view.startAnimation(animation);


Related Topics



Leave a reply



Submit