5

Is anyone aware of any problems with using sp units for layout dimensions? So, say I have a 16sp text, is there any problem with setting TextView height to 20sp for example, so it scales with the text?

<TextView
    android:textSize="16sp"
    android:layout_width="match_parent"
    android:layout_height="20sp"
    ...

This way the padding around the text stays proportional to text size after scaling. Also, this is useful with auto sizing, where using wrap_content is not recommended.

However, the official docs state that sp should never be used for text size (without any explanation though):

When defining text sizes, however, you should instead use scalable pixels (sp) as your units (but never use sp for layout sizes).

What is the reasoning behind this? Both dps and sps are converted to a certain device-specific pixel amount in the end, are they not? What's the core difference then?

zarsky
  • 680
  • 2
  • 14
  • 24

1 Answers1

5

From the documentation: https://developer.android.com/training/multiscreen/screendensities

To preserve the visible size of your UI on screens with different densities, you must design your UI using density-independent pixels (dp) as your unit of measurement. One dp is a virtual pixel unit that's roughly equal to one pixel on a medium-density screen (160dpi; the "baseline" density).

So, the whole idea of dp is to specify a measure that is independent from the screen density.

When defining text sizes, however, you should instead use scalable pixels (sp) as your units (but never use sp for layout sizes). The sp unit is the same size as dp, by default, but it resizes based on the user's preferred text size.

Here the idea is that if the user is visually impaired, he could change the size of the text changing a system setting. Note also the The sp unit is the same size as dp: with a system setting of default size for text, there is no difference between dp and sp. So you should not see any difference in changing your layout size between sp and dp. both will translate to the same amount of pixels.

The reason of but never use sp for layout sizes is merely the fact that you don't want images, buttons or any other layout dimension to scale based on the system preference of the text size. This seems pretty obvious to me.

Accessibility settings: https://support.google.com/accessibility/android/answer/6006972

the code on Android OS that makes the conversion from different units to pixels is: (from https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/android/util/TypedValue.java )

    public static float applyDimension(int unit, float value,
                                       DisplayMetrics metrics)
    {
        switch (unit) {
        case COMPLEX_UNIT_PX:
            return value;
        case COMPLEX_UNIT_DIP:
            return value * metrics.density;
        case COMPLEX_UNIT_SP:
            return value * metrics.scaledDensity;
        case COMPLEX_UNIT_PT:
            return value * metrics.xdpi * (1.0f/72);
        case COMPLEX_UNIT_IN:
            return value * metrics.xdpi;
        case COMPLEX_UNIT_MM:
            return value * metrics.xdpi * (1.0f/25.4f);
        }
        return 0;
    }

And the comment that explains what is scaledDensity: (from https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/util/DisplayMetrics.java )

    /**
     * A scaling factor for fonts displayed on the display.  This is the same
     * as {@link #density}, except that it may be adjusted in smaller
     * increments at runtime based on a user preference for the font size.
     */
    public float scaledDensity;
AndrewBloom
  • 2,171
  • 20
  • 30
  • 1
    Never say never :) Why not? Yes, your layout can become a mess if a user changes the text size **and** you don't take that possibility into account. But if you do, you can help your visually impaired users to see some small details of your layout more clearly. Also I suspect that a small fixed size button barely lager than a string in it won't benefit from `sp` units if they're used only on the string, but not on the button. Am I wrong? – x00 Mar 01 '21 at 16:49
  • 1
    @x00 yes, I agree with you that in some cases it could be a nice workaround. – AndrewBloom Mar 01 '21 at 16:56
  • Basically, I just want to know if there's a chance that there will be some unexpected consequences of using `sp` for layout dimensions, e.g. layout becomes completely broken on some Android version, etc. I'm totally okay with making sure the layout looks good for every particular font size setting. – zarsky Mar 03 '21 at 19:22
  • 1
    Based on this: `case COMPLEX_UNIT_SP: return value * metrics.scaledDensity;`, looks like it just applies a multiplier and returns a number, so should be fine. – zarsky Mar 03 '21 at 19:50