I wonder how to make application look the same on different devices. I have read Supporting Multiple Screens many times but I still can't understand how to live.
Here is a sample layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, MyActivity"
android:textSize="30sp"
/>
</LinearLayout>
There is Galaxy S II (480x800) and Sensation XE (540x960). They are both hdpi, physical screen size is almost the same. I expected to see the same looking on both devices but in fact text on 540x960 is smaller then on 480x800:
(left is 480x800, right is 540x960)
I tried to specify text size as dimension resource and make separate folder values-w540dp but it took no effect.
How do you guys make your application look the same on different hdpi devices?
android:textAppearance="?android:attr/textAppearanceLarge"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textAppearance="?android:attr/textAppearanceSmall"
These atributes may solve your problem here.Otherwise you have to setup your layout dynamically with some ratios(or factors you generate like :textSize=factor*height) using your screen height and width.
Have a look at metrics , if you specify your textsize in dp (Density-independent pixels) it should work. The default size for text should be around 14dp. (TextAppearance.small)
2 Sites that might be helpful as there are some nuggets in both related to your problem, however, neither is an exact 1-2-3 how to correct the issue you're seeing:
http://www.pushing-pixels.org/2011/11/08/deep-dive-into-responsive-mobile-design-part-1.html
http://www.alistapart.com/articles/fluidgrids/
Related
I am currently trying to adjust my Android App so it will look and feel similar on multiple screens/devices.
I know by now that a major part in this is to provide multiple image sizes for every image file according to the x1, x1.5, x2, x3, x4 ratios for mdpi, hdpi, xhpi, xxhdpi and xxxhdpi respectively, and I have finished doing so today.
After doing this, I have defined Density independent Pixel dimensions in the #dimen.xml values resource that correspond with the actual image sizes in pixels of the MDPI resources. Subsequently, i have set the imageviews in question's layout_width and layout_height to this dimension.
I am currently at a loss, however, as to why my application still looks significantly different on an MDPI emulator than it does on an HDPI emulator. To highlight what I mean, I'll provide the following screenshot showing the HDPI and MPDI emulator next to one another (left is HDPI (4" WVGA Nexus S) and right is MDPI (5.4" FWVGA)). I want both of them to look like the MPDI version, but what I've done so far apparently isn't working.
I have three theories of my own as to why this is not working the way I intend it to:
1. I am not supposed to set ImageView layout_width and layout_height to a dp value, but rather match_parent or wrap_content (?) (and change the structure of my .xml layouts in the process).
2. I am not only supposed to define multiple drawable resources, but also multiple layout resources for different screen sizes (?).
3. I have misunderstood the entire idea behind how this is supposed to work (?).
I will also give you an example of one of the list items that can be seen in the first screenshot (#drawable/phone_speed_icon is a 64 x64 pixel resource in MPDI and a 96x96 resource in HDPI, and #dimen/icon_attribute_size is 64dp):
<LinearLayout
android:id="#+id/llSpeed_PreSession"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="10dp"
android:paddingEnd="20dp"
android:paddingStart="20dp"
android:weightSum="100">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="#dimen/icon_attribute_size"
android:layout_weight="20"
android:weightSum="100">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="70"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="#dimen/icon_attribute_size"
android:layout_height="#dimen/icon_attribute_size"
android:src="#drawable/phone_speed_icon" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="30"
android:gravity="center_vertical"
android:paddingStart="10dp"
android:text="Speed"
android:textAppearance="#android:style/TextAppearance.Large"
android:textColor="#878787"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="80"
android:gravity="center">
<android.support.v7.widget.SwitchCompat
android:id="#+id/swSpeed_PreSession"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
In the end, I have four questions that I'd like answered:
1. How do I make the list items in screenshot 1 look the same on MDPI devices as HDPI devices? Does this have anything to do with one of the three theories I mentioned earlier?
2. Why is the header text ("What do you want to measure?") wrapped on one device, but not on the other? They use the sp unit (via android:style/TextApperance.TextApperance.Large)?
3. Shouldn't everything be more spaced out on an HDPI device (if anything) rather than less spaced out? The HDPI emulator looks as if it "has got way less pixels available", if you can understand what I'm saying even a little.
4. How do I make the Fragments on the second screenshot look the same? Or should i not even want this, because the HDPI is (for some reason) physically smaller, which is why the layout is less spread out?
Anyway, I have been at this all day and the more I read the more thouroughly confused I get, so any help is greatly appreciated!
You have the option to create multiple dimens.xml files depending on a variety of factors. Here you'll see what my current project looks like with the various dimens.xml files in Android Studio based on screen width.
However, you can have different requirements for each dimens file you want. For example, you can create dimens files for each density:
I have a fragment that takes up the whole screen, with Buttons and a SeekBar which scale to fit it, as well as fixed size TextViews. I use linear horizontal and vertical layouts with weights to achieve this.
The problem is I can't get the button text large enough without it making the buttons expand in size. For some reason, any text size greater than about 35sp makes the button expand, no matter how big the button is. This screen shot shows the button sizes have plenty of space for the text:
Ideally I would like the "<" and ">" characters to fill the buttons. (I was going to programmatically change the font size according to the button size, e.g. for different screen sizes) but haven't tried since I can't even get the static layout to work.
Edit: I would like to avoid images, since if I had 15 buttons, and 8 buckets, that would be 120 images I need!
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/VerticalLinearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="0dp"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:paddingTop="0dp" >
<!-- ........ -->
<TextView
android:id="#+id/trackTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2" >
<Button
android:id="#+id/trackPreviousButton"
style="android:buttonBarStyle"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="#string/button_track_previous"
android:textSize="35sp" />
<Button
android:id="#+id/trackNextButton"
style="android:buttonBarStyle"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="#string/button_track_next"
android:textSize="35sp" />
</LinearLayout>
<SeekBar
android:id="#+id/seekBar"
style="#style/tallerBarStyle"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<!-- ........ -->
</LinearLayout>
I have tried adding the following line to Buttons, but it only makes a small difference, if any:
android:padding="0dp"
Advice on getting the font height to fill the buttons without padding is my primary question. (But if the problem of dynamically sizing the text to fill the buttons for different screen sizes can be solved at the same time, that would be brilliant).
Edit: it turns out that using larger font sizes affects the effect of weighting for the height of the linear layouts, which is why there seemed to be padding - larger font size increased the button size, not because of the padding (which was 0) but because of the weighting
Button is not the right widget for your purpose. Use an ImageButton (or even an ImageView) instead.
I was going to programmatically change the font size according to the button size, e.g. for different screen sizes
Your current approach will land you in a lot of problems regarding proper sizing of your UI components. Given the plethora of android devices out there, screen size is just one aspect of the problem. You will also be dealing with varying screen densities. Best approach would be to put size/density buckets (drawable-mdpi/hdpi/xhdpi) to use. Help android in working for you.
Use drawables to indicate next and previous. If you're worried about the drawables being too small for tablet screens, create appropriate drawable resources/folders:
// Phones - 4 to 7 in
drawable-ldpi
drawable-mdpi
drawable-hdpi
drawable-xhdpi
drawable-xxhdpi
// Tablets - 7 to 10 in
drawable-large-mdpi
drawable-large-hdpi
// Tablets - 10 in
drawable-xlarge-mdpi
This list may not be exhaustive. Consider doing some research before finalizing your size/density buckets.
Output:
# drawable size 32dp:
# drawable size 64dp
Now it becomes quite straightforward - finalize drawable size by visual inspection on a phone, on a 7 inch tablet, and on a 10 inch tablet. Then use density scales to create and store appropriately sized drawable in the folders I mentioned above. Let android deal with what bucket to pick from.
The problem is by default buttons include a minHeight attribute. I had the same problem and solved it with just a single line of code in my XML file:
android:minHeight="0dp"
There is a quick and easy solution to your problem!
Auto-sizing text in Android is fiendishly difficult in my experience, especially when padding is involved. I would advise that instead of using an angle bracket character, you use a drawable - there are plenty of arrow icons available online - and an ImageButton. For example:
<ImageButton
android:id="#+id/trackNextButton"
style="android:buttonBarStyle"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:src="#drawable/left_arrow"
android:scaleType="fitXY"
android:padding="0dp"
android:textSize="35sp" />
By using different ScaleTypes you can alter the stretching of the image. Even better, the screen sizes problem is solved because you can add different drawables for different densities.
Use minWidth="0" or "1" to reduce the horizontal padding on a text Button.
The attached layout which works correctly for a phone (Samsung Infuse), but it does not show
layout correctly when the app is uploaded to a tablet (Nexus 7). The button sizing is incorrect. How can I fix this?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/"
style="#string/menu_settings"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/gecko25"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:textAlignment="center"
android:visibility="visible" >
<Button
android:id="#+id/link1_btn"
android:layout_width="98dp"
android:layout_height="wrap_content"
android:minHeight="58dip"
android:minWidth="98dip"
android:text="About"
android:textStyle="bold" />
<Button
android:id="#+id/link2_btn"
android:layout_width="98dp"
android:layout_height="wrap_content"
android:minHeight="58dip"
android:minWidth="98dip"
android:text="Experience"
android:textStyle="bold" />
<Button
android:id="#+id/link3_btn"
android:layout_width="98dp"
android:layout_height="wrap_content"
android:minHeight="58dip"
android:minWidth="98dp"
android:selectAllOnFocus="false"
android:text="Bulacards"
android:textStyle="bold" />
</LinearLayout>
Make different layouts for different densities. ie, place the same xml file in layout-hdpi,layout-xhdpi,layout-tvdpi
To create those folders in res/layout follow these steps:
Right click on layout folder --> new-->other-->Andorid xml layout-->next-->give the filename(must be same in all densities)-->AvailableQulaifiers tab select density--> move it to chosen qualifiers with the help of arrow in between--> there select for what density (medium high tv)--->finish
Like for example:
Nexus S and Nexus one ---> hdpi
Galaxy Nexus ----> xhdpi
Nexus 7 ---> tvdpi
and give heights and widths for the Button.. best practice is to set them to wrapcontent , if for your scenario it requires height follow the above steps. and give height and width such that different for phone and tablets which comes under different densities
It's not recommended that you use tvdpi for Nexus 7 screens.
See this:
http://android-developers.blogspot.com/2012/07/getting-your-app-ready-for-jelly-bean.html
Probably the best way to detect 7" tablets (like the Nexus 7) is to use the qualifier:
layout-sw600dp
And the qualifier for 10" tablets:
layout-sw720dp
You might want to try specifying the button sizes in sp rather than dp as they may need to bigger or smaller if the user changes the default font size but wrap_content and/or use weights are usually best.
So my problem is simple- I want to use XML layouts to precisely control the positioning of widgets on multiple devices. To do this, I thoroughly read the google docs on supporting multiple devices. According to this part, the WVGA854 and HVGA are both considered "Normal screen" size. So theoretically, positioning a widget on WVGA854 should look the same as with HVGA. However, the resultant screenshot shows otherwise.
The widget appears relatively higher placed on the WVGA854 skin. The XML code is shown below, and was placed under the layout-normal/ folder:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ImageButton
android:id="#+id/button1"
android:src="#drawable/icon_unlock"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="300dp"
android:text="Button" />
</RelativeLayout>
The drawables I constructed are in the proper ratios (3:4:6:8 as recommended). So why does this positioning mismatch happen? I beginning to think that using XML to position things is quite fruitless. My app requires very accurate positioning of widgets so even this slight mismatch is a problem. Any help how I can remedy this?
EDIT:
What I want is for the widget to be placed in a manner such that the ratio of margin from top to the margin from bottom is exactly the same across devices. From the screenshot, you can see that this ratio is not the same for WQVGA854 and HVGA.
"Normal Screen" size does not mean that screens have the exact same number of dip. You need to think of it as a bucket which contains a number of different screen sizes which are all similar in physical size.
so using fixed size margins and paddings is not (easily) going to achieve the effect you need. So please clarify your question and give an example of what you exactly want to achieve.
When I tested the font size with different density settings using the Eclipse Emulator, I get different size fonts even though I am using "dp" to specific the size. I would have thought the size may decrease with higher density, but I found the higher the density, the bigger the font is. I tried using "in" and "mm" and the same behavior occurs, in that the higher density, the bigger the fonts. This is based on android:minSdkVersion="10".
Is there any way I can set the font sizes to scale to the same size for the different density?
Here is the xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:layout_gravity="center"
android:textColor="#color/orange"
android:textStyle="bold"
android:text="THIS IS A TEST"
android:background="#color/white"/>
</LinearLayout>
Unfortunately I cannot post the images of the font size for the three Emulator settings due to lack of reputation.
Thank you.
I had the same problem... And did't found anything, but making folders:layout-small...large, xlarge, and folders with drawable images for high, mid and small densities with resolutios of images according to it... So, everything works well on different droids with different screens... For every display size there is layout with different meanings of dp...((
Use sp instead of dp
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:layout_gravity="center"
android:textColor="#color/orange"
android:textStyle="bold"
android:text="THIS IS A TEST"
android:background="#color/white"/>
</LinearLayout>
I guess one way is this:
When you make new layout file there is next button in eclipse. Press that and there is a list where to pick layout's density. You can pick x-high density, high density, medium density etc.. When you press finish it makes layout folder like "layout-hdpi" (depends what density you pick). And then make text fit good with that density.
Hope that helps. :)