I am reading through http://developer.android.com/guide/practices/screens_support.html and trying to understand how pre-scaling works.
I have the following layout file which is optimized for the galaxy tab :
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relativelayoutmain"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/mainmenu"
>
<ImageButton
android:id="#+id/start_button"
android:layout_marginLeft="150dip"
android:layout_marginTop ="70dip"
android:layout_width="500dip"
android:layout_height="214dip"
android:background="#drawable/startsession"
android:contentDescription="#string/descbuttonstart"
/>
I have placed the images for the screen in the drawable-ldpi folder. The problem is that when I test the app on a smaller screen (using the emulator) the screen does not scale properly - the button is massive and not positioned correctly.
Is it possible to just have one layout file for all screens and if so what is the secret to getting this working ?
Thank you.
NO , AFAIK its not possible you need to have three differents folders(hdpi,mdpi,ldpi) with different dimensions for buttons,images etc
and also for layout again you need to have three layout folders (layout-small,layout-medium,layout-large)
Screen size and screen resolution are two independent things. the resources in ldpi folder are for low resolution and not necessory small screen sizes. The way I prefer is to define resources for high resolution and let them scale down on others.
Related
I know the Internet is overwhelmed with questions about DPI px inches and so on.
But after several hours of googling my situation doesnt seem to happen to anyone else!
I have 2 devices custom build with android studio which are both mdpi.
BUT one device is 3.65inch and the other device is an 10.1 inch.
I have created a folder with 2 images 250x125 with the dpi set to 160 dpi
If normally I would declare my 2 images in my XML with dp units instead of pixels...I would suppose on both screens the result should be the same right ?
Well it seems the images keep remaining the same size and don't look # how many inch the device is
So to set things clear:
What do I have to change at my resources or my code so that my layout scales identical for different Inch sizes ?
This is my GOOD layout for my mdpi 10.1 tablet :
This is my BAD layout for my mdpi 3.65 device
How can I make it so that even on the 3.65 inch screen the buttons will scale to the same PROPORTIONS as the 10.1. Not the inches...not the pixels...the proportions....
This is my XML File
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:gravity="center">
<Button
android:id="#+id/buttonEnglish"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/english"
android:layout_marginBottom="5sp"
android:layout_marginLeft="5sp"
android:layout_marginRight="2sp"
android:layout_marginTop="0sp" />
<Button
android:id="#+id/buttonNederlands"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/nederlands"
android:layout_marginBottom="5sp"
android:layout_marginLeft="20sp"
android:layout_marginRight="5sp"
android:layout_marginTop="0sp"
/>
</LinearLayout>
I'm desperate...
Thanx in advance
This might help explain the problem you are facing...
You have an image that is 250x125 - that is 250 pixels wide by 125 pixels in height.
You have specified 160 dpi - which means that 1 inch = 160 pixels.
So, both screens are doing what you ask and displaying the 250 pixels across 1.5625 inches. On the large screen it looks "proportionally" correct. On the 3.65" screen the button takes up more than half the screen - just like you asked it to.
If you want the smaller screen to look like the larger screen, then you have three options:
adjust the size of the image and provide 2 image assets (or more for a wider variety of screens). This is why you can have resource folders for mdpi, hdpi, xhdpi, etc. You adjust the pixels in the image to accommodate the screen size.
You use a "weighted" LinearLayout that adjusts the size of the space provided based on the available screen space. For this type of layout you should not worry about performance.
Do runtime scaling of the image based on screen size - use DisplayMetrics to get the size and density of the screen and adjust your image to fit the screen appropriately.
The last option is the most flexible in many ways, because if you end up with a screen that is either very large or very small, you can make adjustments to do things like move buttons or text to another place on the screen (above or below other content). But for your specific problem, any of them will suffice.
There is no need of Designing two xml layout.
You can use Dimension for margin and padding according to device.
You are giving static value for margin.
Use dimen.xml in value folder each device.
Following code in your layout.xml will work for you.
android:layout_marginLeft="#dimen/margin_button"
Value folder name for dimen.xml:
values-mdpi
values-hdpi
values-xhdpi
values-xxhdpi
values-sw600dp
create dimen.xml in each values folder.
and in dimen.xml you have to define value for margin in all values folder but value of that property is different according to device size like this:
values-mdpi
<dimen name="margin_button">20dp</dimen>
values-hdpi
<dimen name="margin_button">23dp</dimen>
like wise in all values folders.
Thanx everyone for the answers. Due to answer from #Iacs I discovered that I had to made changes to my folder structure.
I have completely overlooked the fact that in the /res folder there can be more directories then just the standard "layout" directory. You can create other directories with these names : layout-large, layout-xlarge, layout-small, and so on...
In these folders you can paste your layout.xml and adjust the values...
This is how things look now in my android studio
note the layout folder structure:
And now ofcourse my 2 devices with both the same DPI but different screen size are showing my buttons the way I want them to be showned!
I have an app that displays a bitmap in a TextView as a "drawableTop":
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_weight="1"
android:drawableTop="#drawable/bitmap"
android:gravity="center"
android:text="#string/text" />
The bitmap comes from a PNG file in the res/drawable folder, let's call it bitmap.png.
I need to support multiple screen sizes and densities, and want to find the cheapest way (in term of how many PNG files I need to have in res/* folders) to do it.
Various densities: Phones only
I've come to the conclusion that it's enough to have the bitmap.png in res/drawable-xhdpi folder. When being displayed on phones with high density, it will be displayed as is, while on phones will lower density, it will be scaled down automatically.
In other words, no need for having lower resolution versions of the bitmap.png in res/drawable-hdpi, res/drawable-mdpi etc.
Basically only one version of the PNG file is enough for all phones.
Various densities: Tablets as well
Now, the problem arises if I want to support as well tablets: large and xlarge screens.
On tablets, I want the aspect ratio of the icon to be the same as it was on phones: If the bitmap took 1/4 of the screen on phones, I want it to take 1/4 of the screen on tablets. I cannot reuse the same PNG file as before or it would look too small since the tablet just has more pixels... So for tablets I need a higher res PNG. And this applies both to large screen and xlarge screens.
Which results in the need for 3 folders, and 3 versions of the PNG:
1: res/drawable-xhdpi/bitmap.png
2: res/drawable-large-xhdpi/bitmap.png
3: res/drawable-xlarge-xhdpi/bitmap.png
But 1 and 2 are basically lower res versions of 3.
So is there an easy way to have a single folder not 3?
If you want to keep only one image for all resolutions, why not keep in res/drawable and res/drawable-land folders?
If you are talking about cheapest way to do this (not adding more than one image in drawables), then use 9-Patch Images. If you dont know about it, then have a look n learn usage here:
http://www.androiddom.com/2011/05/android-9-patch-image-tutorial.html
http://www.androiddom.com/2011/05/creating-custom-drawn-button.html
Judging from your question, you don't need different orientated images for tablet or phone.
If you want the image to take 1/4 size on both devices, then define your image in your xml as using d(i)p. This will scale the image to the same size on all devices.
d(i)p is scaled relative to 640x480 (or 480x640 resolution for portrait orientation).
So you can calculate different combinations of resolutions to cover 1/4 screen space, such as 320x240 or 240x320
If you want control over the scaling of your image, I would suggest putting the image in an ImageView. This will allow you to use the android:scaleType property to scale your image how you wish.
You can set the background of your TextView to be transparent, and have the ImageView below it contained within a relativeLayout of your desired size to achieve the same effect as you current have, like so:
<RelativeLayout
android:layout_width="320dp"
android:layout_height="240dp"
>
<!-- Images at the top of the xml are drawn on the bottom! -->
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
android:src="#drawable/bitmap"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="#string/text"
/>
</RelativeLayout>
Also consider using alias resources.
This will allow you to define an xml file which will act as if it's the real PNG image (and is referenced as such in R.drawable. , but is actually a reference to another image.
From the linked Google documentation:
To create an alias to an existing drawable, use the element.
For example:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/icon_ca" />
If you save this file as icon.xml (in an alternative resource
directory, such as res/drawable-en-rCA/), it is compiled into a
resource that you can reference as R.drawable.icon, but is actually an
alias for the R.drawable.icon_ca resource (which is saved in
res/drawable/).
I want to develop an app which will support different screen sizes.
I've read the official guide a lot of times, but I can not understand this. I created a brand new app with a main activity, then I put a black square on the screen with 100dp x 100dp dimensions, just like this:
res/layout/activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#000000"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
/>
</RelativeLayout>
When I run this application on my emulator - I get this screen:
And when I run the application on my device (Galaxy tab 2), I get a screen like this:
As you can see, the square running on device is smaller than running on the emulator.
I am using DP in my XML width and height. Is the square supposed to be in the same proportion in all resolutions? If not, what can I do to get this square in the same size in all resolutions?
Yes, this can be confusing.
However, different devices have different amounts of 'DP's. The purpose of this is so that larger screens can hold more content. If you're using images, you can provide different sizes for different screen densities.
For more info, see this page: http://developer.android.com/guide/practices/screens_support.html
After two years of Android development I'm still not 100% sure about what resources I need to provide to make my GridView work on different size and resolution devices.
I'm still learning, for example I recently discovered that you don't have to supply every drawable in all screen sizes - if you put something in xhdpi then Android is clever enough to resize that on the fly most of the time - but there are a few few quirks. For example if I try using drawables which are only defined in the drawable-xhdpi bin on a mdpi device in a GridView, the drawable will visually resize correctly but the whitespace around it won't - that will still be the original size. Originally I got around this by forcably defining dimensions for all aspects of the GridView and the associated adapter view, but this had a load of code smell around it, so I resized the drawables manually, put them in their respective bins (drawable-mdpi, drawable-hdpi and drawable-xhdpi) and removed all the forcing of image sizes etc.
So I currently have:
<GridView
android:id="#id/home_image_grid"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnWidth="100dp"
android:gravity="center"
android:listSelector="#00000000"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
>
</GridView>
and the layout for each item is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="0dip"
android:gravity="center"
android:orientation="vertical"
android:padding="0dip">
<ImageView
android:id="#id/home_button_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="#id/home_button_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#color/default_text_colour"
android:textSize="#dimen/home_button_text"
/>
</LinearLayout>
So far so good...
The app I'm currently working on I've almost finished and have been doing some testing on different devices - it looks good on normal screen size xhdpi, hdpi & mdpi devices. Then I extending my testing to other devices - I'm testing on an HTC Flyer which is large screen size, mdpi - and the gridview now looks rubbish - it's correctly picking up the mdpi images, which are tiny.
Doing some reading around I found the GridView tutorial GridView tutorial, which says to put all your drawables in the 'drawable' bin, so I followed this advice and again everything looked rubbish - on closer inspection (and having actually read through the example code) it seems that they are manually setting the size of each image in the GridView - which I'd been doing to start off with, and which means that I'm going to have to manually set the image sizes for every permutation of devices.
So..I'm left wondering if I've missed a trick here - should I take my first approach of sticking the images in my drawable folder and manually forcing the sizes for every purmutation? Should I draw a new set of images for all permutations of screen size and resolution?
How can I guarantee that whatever I do, it's going to look good on a device I've not tested it on?
Either way it feels like I'm doing something wrong - but I can't work out how to do this properly without loads of hassle. Can anyone help?
I'm not sure what you mean by "forcing the sizes for every permutation" but you could put the proper sized drawables in the following folders:
drawable-mdpi
drawable-large-mdpi
Each device would pick the right drawables from the corresponding folder and you could separate normal and large images for mdpi devices.
Wouldn't that fix your problem?
P.S: The drawable folder is meant for XML drawables only or photos which do not depend on the device's density, not images for the UI. Those will scale properly for each resolution and density.
I read the
http://developer.android.com/guide/practices/screens_support.html.com?
but couldn't get how to apply this, can anyone give me example with buttons and textview that how would it fit on different devices?
It's not as complicated as you might think. First remember that your basic layout is always designed for mdpi, for a normal screen size with with a medium density (about 160 dpi).
So when you design your layout the important part is that you don't use px as unit when you define your layout. Instead always use dp (Density-independent pixel) as unit as they are automatically scaled to the correct number of px for the current density.
Til this moment you only have one file (e.g. myLayout.xml) for all the different layout sizes (small, normal, large and xlarge). If you think that your layout should be different on a device with a xlarge display, like a tablet then you simply create another folder called layout-xlarge in the same level as layout and another layout file named myLayout.xml. You can now make changes to this file to let the layout look different on devices with a xlarge display. Perhaps you want a larger text box you you want to rearrange
the button and text box.
So as you see, it's not that hard. Just use dp as the unit for dimensions and Android will do the rest for you.
The simplest way to support multiple screens is to place your resources in the different density folders, and layouts in different layout size folders.
For example, have the following folder structure:
AppRoot/
res/
drawable/
drawable-hdpi/
layout/
layout-large/
You can place your bitmaps in the different drawable directories based on their densities and sizes. That sorts out different bitmaps for different density screens.
For different layouts according to screen size, in the layout and layout-large directories put the different layouts to support how you want to display your screen.
Lets take a simple example of a simple list filling screen for a small device, versus a large screen where you may want your list in the 40% of screen, and information to right of this:
layout/main_layout.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
>
<ListView
android:id="#+id/main_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
layout-large/main_layout.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:weightSum="1.0"
>
<LinearLayout
android:orientation="horizontal"
android:layout_weight="0.4"
android:layout_width="0dp"
android:layout_height="fill_parent"
>
<ListView
android:id="#+id/main_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
<LinearLayout
android:id="#+id/details_large"
android:layout_weight="0.6"
android:layout_width="0dp"
android:layout_height="fill_parent"
>
<include layout="#layout/detail_information" />
</LinearLayout>
Now your application can just use "main_layout", and the device will pick the one according to the screen size, which gives you your multiple screen support.
The important point being that the layouts are the same named file main_layout.xml, and android picks the one from the correct folder itself. The same is true of the bitmaps for buttons etc; place the same named bitmap in multiple directories and android sorts out which to use according to the screen density.
I've refrained from putting text views and buttons in these examples, because they're just layout elements that you can fill in as needed.