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 dp
s and sp
s are converted to a certain device-specific pixel amount in the end, are they not? What's the core difference then?
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With