I've been developing apps for months and I've read that using layout-small, layout-large, layout-xlarge and so on to support multiple screen resolutions is deprecated started in Android 3.0(correct me if I'm wrong). Hence, I'm still using multiple layout directories but it's a lot of work when designing an Application.
My questions are:
Is there any way to design a layout to support multiple screens all at once without using multiple layout-size.xml files?
What is the alternative solution when using layout-size directory is deprecated?
You can use dimensions. Basically, you'll have the same thing, with multiple directories, but for the values directory, thus a values, values-sw600dp, values-sw600dp-land etc.
In these, you can have a dimens.xml, with the following content:
<!-- In values/dimens.xml -->
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="my_specific_dimension">150dp</dimen>
//More items...
</resources>
<!-- In values/dimens.xml -->
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="my_specific_dimension">150dp</dimen>
//More items...
</resources>
You can now use #dimen/my_specific_dimension in a single layout file, for example for a width or a height, and it will use, just like for the multiple layouts situation, the correct dimension based on the screen category.
That works only if the layout is basically the same, with different sizes. There's little customisation with that solution. If you want to use different layout, you still have to write multiple layout files. I believe the deprecation of x-large, etc. was after they introduce layout-sw600dp, layout-land, layout-sw600dp-land. Check the documentation for how to declare different layout for different sizes. It explains how to use the sw<N>dp qualifiers.
Unfortunately, there is not a standard layout that supports multiple screens.
For instance Normal layout can display with several inches, and accordingly may be among them some larger height or width. However, it should define be unique layout for each screen.
Related
How to maintain consistent app layouts cross-device?
Per consistency i mean to proportions, readability, usability and user comfort.
For some time I'm doing apps for android. All these applications were made for corporate clients. Each application was designed for a specific phone so i never need mastering the layouts deeply.
Recently, I received a request to build a complex application for all android 2.2 devices and up to 5.0. The requirement includes: ActionBar, Sliding Menu, Master/Detail Flows, Many Fragments, Many buttons, Maps, the list go on. So i begun research.
Research
First, to support all Views mentioned above, I decided to use appcompat_v7. Simply because Google made it. Discard ActionBarSherlock because it's a third party library.
Alternative Layouts:
Under certain conditions, you need to use an alternative layout. This is done easily with an alias.
values-large/aliases.xml
<resources>
<item name="main_layout" type="layout">#layout/main_latyout_large</item>
</resources>
This will make this code:
setContentView(R.layout.main_layout);
Operate effectively as this one
setContentView(R.layout.main_layout_large);
So far so good, but as will be seen later something is escaping me. (see Finally)
Note: An alternative way is to place master_layout_large.xml as layout-large/master_layout.xml.
Scaffolding, proportions
A trivial example:
layout/master_layout.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="#dimen/layout_weightSum">
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="#dimen/view1_weight"/>
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="#dimen/view2_weight"/>
</LinearLatyout>
values/dimens.xml
<resources>
<dimen name="layout_weightSum">1</dimen>
<dimen name="view1_weight">0.2</dimen>
<dimen name="view2_weight">0.8</dimen>
</resources>
This configuration allows me to easily change the proportions as follows:
For Android 2.2 to Android 3.1
values-small/dimens.xml
<resources>
<dimen name="view1_weight">0.3</dimen>
<dimen name="view2_weight">0.7</dimen>
</resources>
For Android 3.2 and up:
values-sh240dp/dimens.xml
<resources>
<dimen name="view1_weight">0.3</dimen>
<dimen name="view2_weight">0.7</dimen>
</resources>
In How to Support Multiple Screens say:
The configuration qualifiers you can use to provide size-specific resources are small, normal, large, and xlarge. For example, layouts for an extra-large screen should go in layout-xlarge/.
Beginning with Android 3.2 (API level 13), the above size groups are deprecated and you should instead use the swdp configuration qualifier to define the smallest available width required by your layout resources.
Then in How Android Finds the Best-matching Resource explains (by an example) the process of resource selection. What is not said (or could find) is how it discard deprecated qualifiers. (even if do)
Q1: Should I use both methods in an application that requires work in all versions?
Q2: Can deprecated resource qualifiers (small,normal,etc) match over non deprecated resource qualifiers?
Note: This technique of scaffolding was taken from here.
Readability:
TextViews are frustrating. Nothing native that supports auto resizing. WTF?.
But suppose I use the component of this response. So i can use the same method, dimensions.
layout/other_layout.xml (relevant code)
<myns.AutoResizeTextView
android:id="#+id/title"
android:textSize="#dimen/title_textSize"/>
values/dimens.xml
<resources>
<dimen name="title_textSize">24dp</dimen>
</resources>
values-xlarge/dimens.xml
<resources>
<dimen name="title_textSize">64dp</dimen>
</resources>
values-sw600dp/dimens.xml
<resources>
<dimen name="title_textSize">64dp</dimen>
</resources>
Same problemas as before, event here the another problem is to show the text in an optimal size for each screen, but is more tedious, because according to my tests, I need to define many variants of the dimension to make it look consistent across devices.
Q3: How to maintain Readability in easy way?
Finally
I realize that the way I'm facing this project the need arises to create multiple value- * and becomes exponentially considering the amount of options out there. (view Providing Alternative Resources)
Q4: What I can do to minimize the amount of value- * that seems to need my application.
Any other sugestion?
I want to know if is there some web or something with examples of dimens.xml files to support multiple screen sizes?
Android runs on a variety of devices that offer different screen sizes and densities. For applications, the Android system provides a consistent development environment across devices and handles most of the work to adjust each application's user interface to the screen on which it is displayed. At the same time, the system provides APIs that allow you to control your application's UI for specific screen sizes and densities, in order to optimize your UI design for different screen configurations. For example, you might want a UI for tablets that's different from the UI for handsets.
Although the system performs scaling and resizing to make your application work on different screens, you should make the effort to optimize your application for different screen sizes and densities. In doing so, you maximize the user experience for all devices and your users believe that your application was actually designed for their devices—rather than simply stretched to fit the screen on their devices.
Follow This Link
Yes You can make folders of values for in which different dimens values are stored for multiple screen resolutions:
for example you can make folder in res named, values-720x1280, values-320x480, values-240x320 and put dimens.xml in each folder with different values in it...
you can define custom height with dimens(Suppose for 720X1280 device) like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="icon_width">55dip</dimen>
<dimen name="icon_height">55dip</dimen>
<dimen name="photo_width">170dip</dimen>
<dimen name="photo_height">155dip</dimen>
</resources>
and for values-320x480 dimens.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="icon_width">20dip</dimen>
<dimen name="icon_height">20dip</dimen>
<dimen name="photo_width">100dip</dimen>
<dimen name="photo_height">100dip</dimen>
</resources>
Then reference them in your other xml:
android:layout_height="#dimen/icon_height">
try it now and tell your experience
From HoneyComb, there is a new way to fix all of this. Your resources folder should now look like this:
I want to use different font size for different screen sizes.
I read about this many articles, but I'm not sure about usage. Is correct to use different dimens resource file for different screen dimensions like code below:
res/values/dimens.xml
res/values-small/dimens.xml
res/values-normal/dimens.xml
res/values-xlarge/dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="text_size">18sp</dimen>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="text_size">24sp</dimen>
</resources>
...
I also read that correct way is to use sp for font size, but this doesn't fit font in different screen dimensions as I expect.
If there, what are the disadvantages of using different dimens for every size?
Thanks
The best way is to create different layout resources for each of the screens you wish to support. Place each of the layouts in a separate folder that designates the width of the screen. For example, normal sized layouts go in your res/layout folder, and a layout resource for a 7 inch tablet (600 pixel width) would go in the res/layout-sw600dp folder. Make the resource names identical, but adjust your font sizes accordingly.
#up Not, it isn't good way.
#topic You can gets width & height of screen (and w&h of View). Next, you can set font, for example 2% of width screen. If you have content 1260x720, 0.02*1260=24,6 px (you can use also (int)24.6 to convert double to int)
I do something very similar and it's worked fine for me. Some people put the values in the various layouts such as Fietser suggested, but if all of your layouts end up being the exact same except for the font size, your approach is better. That way you can have a single layout and only modify the font sizes. But sometimes you might have changes in the actual layout xml, so then it's probably a wash between the two approaches.
My application shows either a one-pane UI or a two-pane UI depending on the screen configuration. On smaller screens, it should be one-pane both on portrait and landscape. On mid-sized screens (anything with a "smallest width" of 600dp and up), the landscape orientation accomodates the two-pane layout pretty well, but on portrait orientation, it should use the one-pane layout. On larger screens, it should use the two-pane layout on both orientations. I also want to support the 3.2+ style qualifiers (like sw600dp and sw720dp) as well as the older "size bucket" qualifier ("xlarge").
The most direct way to do this is create several different XML layout files, one for each configuration:
res/layout-sw600dp-land/main.xml
res/layout-sw600dp-port/main.xml
res/layout-sw720dp-land/main.xml
res/layout-sw720dp-port/main.xml
res/layout-xlarge-port/main.xml
res/layout-xlarge-land/main.xml
res/layout-port/main.xml
res/layout/main.xml
As a result, there's a lot of code duplication in these 8 XML files which essentially describe only two distinct layouts.
How can I do this without having to maintain all these duplicate XML files, which are a maintenance headache?
You can use layout aliases. Rather than describing your layout directly in the XML files for each screen configuration, you should define your two layouts in two XML files called, say, "onepane.xml" and "twopanes.xml". These files go in res/layout.
Now, you have to map these layouts to your different screen configuration, and that's where the "layout alias" technique comes in handy. For each screen qualifier combination, create an XML file in res/values-X/layout.xml, where X is the qualifier combination. In that file, declare a layout resource that points to either #layout/onepane or #layout/twopanes, as appropriate:
res/values-sw600dp-land/layout.xml:
<resources>
<item name="main" type="layout">#layout/twopanes</item>
</resources>
res/values-sw600dp-port/layout.xml:
<resources>
<item name="main" type="layout">#layout/onepane</item>
</resources>
Do the same for your other configuration combinations, and that way you can accomplish what you're looking for: you can map your two layouts (onepane and twopane) to several different screen configurations without having to duplicate your layout.
For more information about this, take a look at the "Supporting Multiple Screens" lesson on Android Training:
http://developer.android.com/training/multiscreen/screensizes.html#TaskUseAliasFilters
For instance, in a specific layout I have the following XML:
<GridView
android:id="#+id/gridView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="3dp"
android:columnWidth="48dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="spacingWidth" />
This grid view is specific to this layout and I don't think I'll be using any other grid views with similar properties. That to say that the dimension values in the code are specific to that grid view.
Should I still move them to a dimens.xml file or it's fine to just leave them like that? If so, should I place values in the dimens.xml file only when that value is used across multiple layouts?
I drop dimension values into a dimens.xml resource typically for three reasons:
Reuse: I need multiple widgets or layouts to use the same value and I only want to change it once when updating or tweaking across the application.
Density Difference: If I need the dimension to be slightly smaller or larger from ldpi -> hdpi or small -> large.
Reading in from code: When I'm instantiating a view in the code and want to apply some static dimensions, putting them in dimens.xml as dp (or dip) allowing me to get a scaled value in Java code with Resources.getDimensionPixelSize().
Supplemental answer
#Devunwired lists 3 reasons to use dimens.xml. Here are the details of how to do that.
1. Reuse
If you set some dp or sp value in dimens.xml once like this
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="textview_padding">16dp</dimen>
<dimen name="large_text_size">30sp</dimen>
</resources>
you can reuse it throughout your app in multiple locations.
<TextView
android:padding="#dimen/textview_padding"
android:textSize="#dimen/large_text_size"
... />
<TextView
android:padding="#dimen/textview_padding"
android:textSize="#dimen/large_text_size"
... />
Then when you need to make a change, you only need to do it in one place.
Notes
This is basically the same effect as using a style or theme.
Be careful not to give two different views the same dimen value if they really shouldn't be. If you need to make changes to one set of views but not another, then you will have to go back to each one individually, which defeats the purpose.
2. Size Difference
#Devunwired called this Density difference, but if you are using dp (density independent pixels), this already takes care are the density difference problem for all but the most minor cases. So in my opinion, screen size is a more important factor for using dimens.xml.
An 8dp padding might look great on a phone, but when the app is run on a tablet, it looks too narrow. You can solve this problem by making two (or more) different versions of dimens.xml.
Right click your res folder and choose New > Value resource file. Then write in dimens and choose Smallest Screen Width. Write in 600 for the width (7” tablet). (There are other ways of choosing the sizes. See the documentation and this answer for more.)
This will make another values folder that will be used for devices whose smallest screen width is 600dp. In the Android view the two dimens.xml files look like this.
Now you can modify them independently.
values/dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="my_default_padding">16dp</dimen>
</resources>
values-sw600dp/dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="my_default_padding">64dp</dimen>
</resources>
When using your dimen you only have to set it with the name you used in both dimens.xml files.
<LinearLayout
...
android:padding="#dimen/my_default_padding">
</LinearLayout>
The system will automatically choose the right value for you depending on the device the user is using.
3. Reading in from code
Sometimes it is a pain scaling programmatically between px and dp (see this answer for how).
If you have a fixed dp value already defined in dimens.xml like this
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="my_dp_value">16dp</dimen>
</resources>
Then you can easily get it with
int sizeInPixels = getResources().getDimensionPixelSize(R.dimen.my_dp_value);
and it will already be converted to pixels for whatever density device the user has.
The dimens.xml file is used to keep all the hard-coded pixel values in one place.
Now, although you may not repeatedly use these values right now, it's still a good idea to to place them in dimens.xml for future reference. Besides, following a standard Android programming paradigm helps other developers to understand your code faster. This is much like the strings.xml where we place Strings some of which end up being used only once! :)
I don’t know if it can help you but I wrote a little java programe that allows you to duplicate a dimension xml file with a new desired value so that you no longer have to do it by hand line by line.
https://github.com/Drex-xdev/Dimensions-Scalable-Android