123

I know, it was discussed already 1000 times, but I can't adjust the text size for different screen sizes. I try to use 'sp' as size units in my custom style:

<style name="CustumButtonStyle" parent="@android:style/Widget.Button">
    ...
    <item name="android:textSize">30sp</item>
    ...
</style>

In 2.7 QVGA it looks OK:

2.7QVGA 30sp

But in 7in WSVGA it looks like this:

7in WSVGA 30sp

I've tried to use both 'sp' and 'dp' with the same result.

Could you please explain how to make these buttons look the same on any screen?

The full custom button style

<style name="CustumButtonStyle" parent="@android:style/Widget.Button">
    <item name="android:background">@drawable/custom_button</item>
    <item name="android:layout_width">fill_parent</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:layout_margin">3dp</item>
    <item name="android:textColor">#ffffff</item>
    <item name="android:gravity">center</item>
    <item name="android:textSize">30sp</item>
    <item name="android:textStyle">bold</item>
    <item name="android:shadowColor">#000000</item>
    <item name="android:shadowDx">1</item>
    <item name="android:shadowDy">1</item>
    <item name="android:shadowRadius">2</item>
</style>

And in my application theme I have

<item name="android:buttonStyle">@style/CustumButtonStyle</item>

And there is my layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/RelativeLayout1"
android:layout_width="fill_parent"
android:background="@drawable/grid"
android:gravity="center"
android:orientation="vertical" android:layout_height="fill_parent">

<Button
    android:id="@+id/buttonContinue"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_gravity="center"
    android:gravity="center"
    android:text="@string/continue_game" android:layout_marginTop="3dp" android:layout_marginBottom="3dp"/>



<Button
    android:id="@+id/buttonNewGame"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/buttonContinue"
    android:layout_alignRight="@+id/buttonContinue"
    android:layout_below="@+id/buttonContinue"
    android:layout_gravity="center"
    android:gravity="center"
    android:text="@string/new_game" android:layout_marginTop="3dp" android:layout_marginBottom="3dp"/>



<Button
    android:id="@+id/ButtonAbout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/buttonNewGame"
    android:layout_alignRight="@+id/buttonNewGame"
    android:layout_below="@+id/buttonNewGame"
    android:layout_gravity="center"
    android:gravity="center"
    android:text="@string/about" android:layout_marginTop="3dp" android:layout_marginBottom="3dp"/>

Axalo
  • 2,765
  • 4
  • 21
  • 35
forcelain
  • 1,496
  • 3
  • 13
  • 16

12 Answers12

166

@forcelain I think you need to check this Google IO Pdf for Design. In that pdf go to Page No:77 in which you will find how there suggesting for using dimens.xml for different devices of android for Example see Below structure :

res/values/dimens.xml

res/values-small/dimens.xml

res/values-normal/dimens.xml

res/values-large/dimens.xml

res/values-xlarge/dimens.xml

for Example you have used below dimens.xml in values.

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <dimen name="text_size">18sp</dimen>
</resources>

In other values folder you need to change values for your text size .

Note: As indicated by @espinchi the small, normal, large and xlarge have been deprecated since Android 3.2 in favor of the following:

Declaring Tablet Layouts for Android 3.2

For the first generation of tablets running Android 3.0, the proper way to declare tablet layouts was to put them in a directory with the xlarge configuration qualifier (for example, res/layout-xlarge/). In order to accommodate other types of tablets and screen sizes—in particular, 7" tablets—Android 3.2 introduces a new way to specify resources for more discrete screen sizes. The new technique is based on the amount of space your layout needs (such as 600dp of width), rather than trying to make your layout fit the generalized size groups (such as large or xlarge).

The reason designing for 7" tablets is tricky when using the generalized size groups is that a 7" tablet is technically in the same group as a 5" handset (the large group). While these two devices are seemingly close to each other in size, the amount of space for an application's UI is significantly different, as is the style of user interaction. Thus, a 7" and 5" screen should not always use the same layout. To make it possible for you to provide different layouts for these two kinds of screens, Android now allows you to specify your layout resources based on the width and/or height that's actually available for your application's layout, specified in dp units.

For example, after you've designed the layout you want to use for tablet-style devices, you might determine that the layout stops working well when the screen is less than 600dp wide. This threshold thus becomes the minimum size that you require for your tablet layout. As such, you can now specify that these layout resources should be used only when there is at least 600dp of width available for your application's UI.

You should either pick a width and design to it as your minimum size, or test what is the smallest width your layout supports once it's complete.

Note: Remember that all the figures used with these new size APIs are density-independent pixel (dp) values and your layout dimensions should also always be defined using dp units, because what you care about is the amount of screen space available after the system accounts for screen density (as opposed to using raw pixel resolution). For more information about density-independent pixels, read Terms and concepts, earlier in this document. Using new size qualifiers

The different resource configurations that you can specify based on the space available for your layout are summarized in table 2. These new qualifiers offer you more control over the specific screen sizes your application supports, compared to the traditional screen size groups (small, normal, large, and xlarge).

Note: The sizes that you specify using these qualifiers are not the actual screen sizes. Rather, the sizes are for the width or height in dp units that are available to your activity's window. The Android system might use some of the screen for system UI (such as the system bar at the bottom of the screen or the status bar at the top), so some of the screen might not be available for your layout. Thus, the sizes you declare should be specifically about the sizes needed by your activity—the system accounts for any space used by system UI when declaring how much space it provides for your layout. Also beware that the Action Bar is considered a part of your application's window space, although your layout does not declare it, so it reduces the space available for your layout and you must account for it in your design.

Table 2. New configuration qualifiers for screen size (introduced in Android 3.2). Screen configuration Qualifier values Description smallestWidth swdp

Examples: sw600dp sw720dp

The fundamental size of a screen, as indicated by the shortest dimension of the available screen area. Specifically, the device's smallestWidth is the shortest of the screen's available height and width (you may also think of it as the "smallest possible width" for the screen). You can use this qualifier to ensure that, regardless of the screen's current orientation, your application's has at least dps of width available for its UI.

For example, if your layout requires that its smallest dimension of screen area be at least 600 dp at all times, then you can use this qualifier to create the layout resources, res/layout-sw600dp/. The system will use these resources only when the smallest dimension of available screen is at least 600dp, regardless of whether the 600dp side is the user-perceived height or width. The smallestWidth is a fixed screen size characteristic of the device; the device's smallestWidth does not change when the screen's orientation changes.

The smallestWidth of a device takes into account screen decorations and system UI. For example, if the device has some persistent UI elements on the screen that account for space along the axis of the smallestWidth, the system declares the smallestWidth to be smaller than the actual screen size, because those are screen pixels not available for your UI.

This is an alternative to the generalized screen size qualifiers (small, normal, large, xlarge) that allows you to define a discrete number for the effective size available for your UI. Using smallestWidth to determine the general screen size is useful because width is often the driving factor in designing a layout. A UI will often scroll vertically, but have fairly hard constraints on the minimum space it needs horizontally. The available width is also the key factor in determining whether to use a one-pane layout for handsets or multi-pane layout for tablets. Thus, you likely care most about what the smallest possible width will be on each device. Available screen width wdp

Examples: w720dp w1024dp

Specifies a minimum available width in dp units at which the resources should be used—defined by the value. The system's corresponding value for the width changes when the screen's orientation switches between landscape and portrait to reflect the current actual width that's available for your UI.

This is often useful to determine whether to use a multi-pane layout, because even on a tablet device, you often won't want the same multi-pane layout for portrait orientation as you do for landscape. Thus, you can use this to specify the minimum width required for the layout, instead of using both the screen size and orientation qualifiers together. Available screen height hdp

Examples: h720dp h1024dp etc.

Specifies a minimum screen height in dp units at which the resources should be used—defined by the value. The system's corresponding value for the height changes when the screen's orientation switches between landscape and portrait to reflect the current actual height that's available for your UI.

Using this to define the height required by your layout is useful in the same way as wdp is for defining the required width, instead of using both the screen size and orientation qualifiers. However, most apps won't need this qualifier, considering that UIs often scroll vertically and are thus more flexible with how much height is available, whereas the width is more rigid.

While using these qualifiers might seem more complicated than using screen size groups, it should actually be simpler once you determine the requirements for your UI. When you design your UI, the main thing you probably care about is the actual size at which your application switches between a handset-style UI and a tablet-style UI that uses multiple panes. The exact point of this switch will depend on your particular design—maybe you need a 720dp width for your tablet layout, maybe 600dp is enough, or 480dp, or some number between these. Using these qualifiers in table 2, you are in control of the precise size at which your layout changes.

For more discussion about these size configuration qualifiers, see the Providing Resources document. Configuration examples

To help you target some of your designs for different types of devices, here are some numbers for typical screen widths:

320dp: a typical phone screen (240x320 ldpi, 320x480 mdpi, 480x800 hdpi, etc).
480dp: a tweener tablet like the Streak (480x800 mdpi).
600dp: a 7” tablet (600x1024 mdpi).
720dp: a 10” tablet (720x1280 mdpi, 800x1280 mdpi, etc).

Using the size qualifiers from table 2, your application can switch between your different layout resources for handsets and tablets using any number you want for width and/or height. For example, if 600dp is the smallest available width supported by your tablet layout, you can provide these two sets of layouts:

res/layout/main_activity.xml # For handsets res/layout-sw600dp/main_activity.xml # For tablets

In this case, the smallest width of the available screen space must be 600dp in order for the tablet layout to be applied.

For other cases in which you want to further customize your UI to differentiate between sizes such as 7” and 10” tablets, you can define additional smallest width layouts:

res/layout/main_activity.xml # For handsets (smaller than 600dp available width) res/layout-sw600dp/main_activity.xml # For 7” tablets (600dp wide and bigger) res/layout-sw720dp/main_activity.xml

For 10” tablets (720dp wide and bigger)

Notice that the previous two sets of example resources use the "smallest width" qualifier, swdp, which specifies the smallest of the screen's two sides, regardless of the device's current orientation. Thus, using swdp is a simple way to specify the overall screen size available for your layout by ignoring the screen's orientation.

However, in some cases, what might be important for your layout is exactly how much width or height is currently available. For example, if you have a two-pane layout with two fragments side by side, you might want to use it whenever the screen provides at least 600dp of width, whether the device is in landscape or portrait orientation. In this case, your resources might look like this:

res/layout/main_activity.xml # For handsets (smaller than 600dp available width) res/layout-w600dp/main_activity.xml # Multi-pane (any screen with 600dp available width or more)

Notice that the second set is using the "available width" qualifier, wdp. This way, one device may actually use both layouts, depending on the orientation of the screen (if the available width is at least 600dp in one orientation and less than 600dp in the other orientation).

If the available height is a concern for you, then you can do the same using the hdp qualifier. Or, even combine the wdp and hdp qualifiers if you need to be really specific.

030
  • 8,013
  • 8
  • 63
  • 100
Herry
  • 6,706
  • 7
  • 46
  • 76
  • 7
    These small/normal/large/xlarge are deprecated at the moment (Dec 2014). The preferred way now is using "swxxxdp". See http://developer.android.com/guide/practices/screens_support.html#range – espinchi Dec 05 '14 at 18:22
  • 1
    @espinchi thank you, you should post this also as an answer. Are there also any recommended dp's? for example standards are: 100sw, 200sw, 400sw, 600sw. – Vince V. May 27 '15 at 11:07
21

I think its too late to reply on this thread. But I would like to share my idea or way to resolve text size problem over difference resolution devices. Many android developer sites suggest that we have to use sp unit for text size which will handle text size for difference resolution devices. But I am always unable to get the desired result. So I have found one solution which I am using from my last 4-5 projects and its working fine. As per my suggestion, you have to place the text size for each resolution devices, which is bit tedious work, but it will fulfill your requirement. Each developer has must listen about the ratio like 4:6:8:12 (h:xh:xxh:xxxh respectively). Now inside your project res folder you have to create 4 folder with dimens file e.g.

  1. res/values-hdpi/dimens.xml
  2. res/values-xhdpi/dimens.xml
  3. res/values-xxhdpi/dimens.xml
  4. res/values-xxxhdpi/dimens.xml

Now inside dimens.xml file you have to place text sizes. I am showing you code for values-hdpi, similarly you have to place code for other resolution values/dimens.xml file.

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <dimen name="text_size">4px</dimen>
</resources>

For other resolutions it is like xhdpi : 6px, xxhdpi : 8px, xxxhdpi : 12px. This is calculated with the ratio (3:4:6:8:12) I have written above. Lets discuss other text size example with above ratio. If you want to take text size of 12px in hdpi, then in other resolution it would be

  1. hdpi : 12px
  2. xhdpi : 18px
  3. xxhdpi : 24px
  4. xxxhdpi : 36px

This is the simple solution to implement required text size for all resolutions. I am not considering values-mdpi resolution devices here. If any one want to include text size for this resolution then ration is like 3:4:6:8:12. In any query please let me know. Hope it will help you people out.

Rahul Sharma
  • 8,050
  • 6
  • 18
  • 29
  • 4
    Isn't bad practice to use px instead of sp in text size? Is there a way to achieve the following ratio using sp instead of px? – Red M Aug 04 '18 at 17:32
  • I checked this is working fine, but I am still confused is it a good practice to use values in px instead of dp/sp? I have never seen somewhere from official documentation to use values in px. – shaby Dec 29 '18 at 11:23
  • 1
    use sp for font size, that's the law. Approach which Rahul showed is correct, just use sp instead of px. – Mihir Patel Feb 15 '19 at 05:34
  • sp should be use if planing to link the app font size with system font size.Otherwise this solution is not bad. – Irfan Ul Haq Jan 03 '20 at 06:22
14

Sometimes, it's better to have only three options

 style="@android:style/TextAppearance.Small"

Use small and large to differentiate from normal screen size.

<TextView
            android:id="@+id/TextViewTopBarTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            style="@android:style/TextAppearance.Small"/>

For normal, you don't have to specify anything.

<TextView
            android:id="@+id/TextViewTopBarTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

Using this, you can avoid testing and specifying dimensions for different screen sizes.

kalan nawarathne
  • 1,804
  • 27
  • 26
10

I did same by dimension and paint something like (with dp but only for text and in drawText())

XML:

   <dimen name="text_size">30sp</dimen>

Code:

   Paint p =new Paint();
       p.setTextSize(getResources().getDimension(R.dimen.text_Size));
Kevin van Mierlo
  • 8,967
  • 5
  • 39
  • 66
LifeStyle
  • 395
  • 1
  • 10
8

Everyone can use the below mentioned android library that is the easiest way to make text sizes compatible with almost all devices screens. It actually developed on the basis of new android configuration qualifiers for screen size (introduced in Android 3.2) SmallestWidth swdp.

https://github.com/intuit/sdp

Muhammad Maqsood
  • 1,209
  • 14
  • 16
  • 2
    [sdp](https://github.com/intuit/sdp) is for screen size; use [ssp](https://github.com/intuit/ssp) for text size – ecle Jan 12 '19 at 02:38
  • This works for me, but I suspect there are too much files to add, this will increase the size of app, @Muhammad you can resize and add only classes whatever needs – Kirtikumar A. Oct 21 '19 at 11:55
  • Looks like this library is not maintained anymore. – Luciano Brum Apr 30 '21 at 13:46
1

To unify all of the screens to show same element sizes including font size: - Design the UI on one screen size with whatever sizes you find appropriate during the design i.e. TextView font size is 14dp on default screen size with 4'6 inches.

  • Programmatically calculate the physical screen size of the other phones i.e. 5'2 inches of other phones/screens.

  • Use a formula to calculate the percentage difference between the 2 screens. i.e. what's the % difference between 4'6 and 5'2.

  • Calculate the pixel difference between the 2 TextViews based on the above formula.

  • Get the actual size (in pixels) of the TextView font-size and apply the pixels difference (you calculated earlier) to the default font-size.

With this way you can apply dynamic aspect ratio to all of screen sizes and the result is great. You'll have identical layout and sizes on each screen.

It can be a bit tricky at first but totally achieves the goal once you figure the formula out. With this method you don't need to make multiple layouts just to fit different screen sizes.

SolidSnake
  • 20,635
  • 18
  • 68
  • 89
  • I would not recommend this, the calculation of the screen size in inches is very unreliably. – Zui0per Jan 28 '21 at 01:27
  • @Zui0per - I've already implemented this approach in my application and it looked good in all screen sizes. You'll basically have same sized UI elements on all of the screens unless if you don't want that then you should use different layouts for different screens. – SolidSnake Jan 28 '21 at 01:40
  • I have tried it and the calculation of the text size does not work properly. (https://www.codepile.net/pile/AX46avDn) Maybe you can have a quick look? :) However, the calculation of the screen size in inches is very unreliable. Sometimes I get weird values on certain devices because of inconsistencies in xdpi and ydpi. Furthermore, if the user changes his device resolution the text size changes too. – Zui0per Jan 28 '21 at 11:00
  • @Zui0per - you can always add that into consideration when you write the formula. There's always a better way to enhance this approach and there will be always corner cases where you need to put into consideration. I basically stated it to give an idea of how to get started – SolidSnake Jan 28 '21 at 17:16
1

If you have API 26 then you might consider using autoSizeTextType:

<Button
  app:autoSizeTextType="uniform" />

Default setting lets the auto-sizing of TextView scale uniformly on horizontal and vertical axes.

https://developer.android.com/guide/topics/ui/look-and-feel/autosizing-textview

  • 1
    The problem with this is that it doesn't uniformly change the text size for multple textviews with Strings of different lengths – Sourabh May 26 '20 at 14:00
0

You can also use weightSum and layout_weight property to adjust your different screen.

For that, you have to make android:layout_width = 0dp, and android:layout_width = (whatever you want);

Martyns
  • 2,383
  • 14
  • 22
Harshit
  • 1
  • 2
0

I know it's late but this might help someone...

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:autoSizeTextType="uniform"
        android:gravity="center_horizontal|bottom"
        android:text="Your text goes here!"
        android:layout_centerInParent="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent="0.05"
        app:layout_constraintHorizontal_bias="0.50"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.50"
        app:layout_constraintWidth_percent="0.50" />
</androidx.constraintlayout.widget.ConstraintLayout>

Also, if you want to adjust the text size then try changing

app:layout_constraintWidth_percent="0.50" 
app:layout_constraintHeight_percent="0.05"

That's all.

Tyler2P
  • 1,391
  • 1
  • 9
  • 18
0

I think you can archive that by add multiple layout resource for each screen size, example:

res/layout/my_layout.xml             // layout for normal screen size ("default")
res/layout-small/my_layout.xml       // layout for small screen size with small text
res/layout-large/my_layout.xml       // layout for large screen size with larger text
res/layout-xlarge/my_layout.xml      // layout for extra large screen size with even larger text
res/layout-xlarge-land/my_layout.xml // layout for extra large in landscape orientation

Reference: 1.http://developer.android.com/guide/practices/screens_support.html

NguyenDat
  • 4,079
  • 3
  • 43
  • 45
-1

As @espinchi mentioned from 3.2 (API level 13) size groups are deprecated. Screen size ranges are the favored approach going forward.

-3

Do not hardcode the sizes.

For flexibility ad new screen resolutions - the best practice is to place dummy TextView into layout to obtain the textSize:

<TextView
        android:id="@+id/dummyTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"
        android:text="TextView" />

And in your code for example:

TextView testTextView = (TextView) rootView.findViewById(R.id.dummyTextView);
float textSize = testTextView.getTextSize();

Keep textSize as a reference to which you can add constant or percetage size (by calculating).

Athlan
  • 5,375
  • 4
  • 33
  • 52