Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use scalable pixels for layout dimensions?

Tags:

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?

like image 629
zarsky Avatar asked Feb 26 '21 18:02

zarsky


1 Answers

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;
like image 193
AndrewBloom Avatar answered Sep 30 '22 18:09

AndrewBloom