Andreas
Andreas

Reputation: 10077

How to make font a bit larger or smaller in a TextView relative to its size

How can I make the font size in a TextView a bit larger or smaller relative to the current font size?

I see many people using hard-coded font size values like 15sp but I'd like to avoid that because I want to be independent of the current font size. Instead, I was thinking of multiplying the font size by 1.2 to make it larger and by 0.8 to make it smaller, e.g. like this:

// make font larger
float size = textView.getTextSize()*1.2;
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);

Still, I'm wondering if this is the best way to do it because it looks a little awkward. That's why I'd like to ask if there's a more convenient way to make the default TextView a bit larger or smaller without hard-coding values like 15sp...

EDIT

I should add that I'm creating everything programmatically. I'm not using XML. So the TextView is created like this:

TextView tv = new TextView(context);

By doing it like this, tv will use Android's default font settings. Now I want to make the font in tv larger or smaller, programmatically in Java.

Upvotes: 0

Views: 1694

Answers (2)

Giorgos Neokleous
Giorgos Neokleous

Reputation: 1767

sp values are used for text. The SP stands for "scalable pixels". The benefit of using the sp is that it would scale according to the user's preferences.

I would suggest not do any calculations manually. The value that textView.getTextSize() will return will essentially be of a "density-independent pixels" (for textSize will be sp). That value will most probably come from your theme.

Using density-independent pixels is the proper way (or autosizing which still uses dp or sp). What you are trying to achieve will be messy and you will have no idea how it will scale on runtime. Using the "hardcoded" values such as 15sp it won't stop from the text from scaling according to the font size but on the contrary, it will be calculated accordingly. To give you an example, 15sp will translate as such:

For 100% font size:

  • ldpi 11.25px
  • mdpi 15.00px
  • hdpi 22.50px
  • xhdpi 30.00px
  • xxhdpi 45.00px

For 75% font size:

  • ldpi 8.44px
  • mdpi 11.25px
  • hdpi 16.88px
  • xhdpi 22.50px
  • xxhdpi 33.75px

What you can do is use Autosizing into Textview.

To use auto-sizing you will need to convert your textview from:

<TextView android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="24sp" />

To:

<TextView android:layout_width="match_parent"
    android:layout_height="200dp"
    app:autoSizeMaxTextSize="24sp"
    app:autoSizeMinTextSize="16sp"
    app:autoSizeStepGranularity="1sp"
    app:autoSizeTextType="uniform" />

Programmatically:

TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(
    textView,
    16, // min
    24, // max
    1, //granularity step
    TypedValue.COMPLEX_UNIT_SP
)

The above means that:

  • Minimum Text size is 16sp.
  • Maximum Text size is 24sp.
  • If the text size is not either of the max or min, then it will scale up or down by 1sp. So all the available values will be 16, 17, 18, 19, 20, 21, 22, 23, 24.

Note: To use AutoSize in TextView, ensure that you don't use wrap_content as it could lead to issues. I would suggest using a hardcoded value or if you are using ConstraintLayout to constraint it with percent, or actual constraints that restrict the size of the view.

Read more:

  1. Support different pixel densities
  2. Autosizing TextViews
  3. Making the most of TextView auto-sizing on Android by Nick Rout
  4. Calculator for DPI

Upvotes: 1

Misha Akopov
Misha Akopov

Reputation: 13057

Override attachBaseContext() of (base)activity and set there fontScale

override fun attachBaseContext(newBase: Context?) {
        val config =  Configuration()
        config.setToDefaults();
        config.fontScale = Random.nextFloat()*2;  // Here Goes scale value for 
        val context = newBase?.createConfigurationContext(config);
        super.attachBaseContext(context);
}

In the example I made it scale randomly every time, you can save somewhere needed scale value and set it here.

    btnChangeSize.setOnClickListener {
        recreate()
    }

Will make this function call and all texts will be scaled as you wanted

Upvotes: 0

Related Questions