Learning some Android development through trial and error, however I'm having a slight issue with the rendering of buttons on top of an image view depending on the resolution of the phone.
I have an imageview with two imagebuttons (at the moment) on top. They are relative to the imageview. I will post the xml markup below. The issue is when I run this on the "Nexus 4" in Android studio, everything looks correct. When I debug through my Samsung Galaxy S4, the imagebuttons are off slightly, and I'm not sure why this would be a problem if everything is truly relative to the imageview. I understand that the resolutions are different, but how would one go about making sure that this renders the same on the smallest of screens, as well as the newer 1080p screens that are becoming more popular?
I can post pictures if need be, but I feel that the xml will provide adequate information on the issue.
Any help is appreciated. Thanks in advance!
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/SRMap"
android:layout_alignParentTop="false"
android:layout_alignParentLeft="false"
android:background="#drawable/sr_map"
android:layout_columnSpan="2"
android:layout_rowSpan="1"
android:layout_column="0"
android:layout_row="0"
android:contentDescription="Map of Summoners Rift"
android:cropToPadding="false"
android:layout_marginBottom="177dp"/>
<ImageButton
android:layout_width="15dp"
android:layout_height="15dp"
android:id="#+id/BlueSideAlert_BlueBuff"
android:background="#drawable/blue_alert_circle"
android:layout_alignTop="#+id/SRMap"
android:layout_alignLeft="#+id/SRMap"
android:layout_marginLeft="90dp"
android:layout_marginTop="128dp"/>
<ImageButton
android:layout_width="15dp"
android:layout_height="15dp"
android:id="#+id/BlueSideAlert_RedBuff"
android:background="#drawable/blue_alert_circle"
android:layout_alignTop="#+id/SRMap"
android:layout_alignLeft="#+id/SRMap"
android:layout_marginLeft="180dp"
android:layout_marginTop="215dp"/>
but how would one go about making sure that this renders the same on the smallest of screens, as well as the newer 1080p screens that are becoming more popular?
See the Docs here about supporting different screen sizes/resolutions. You create separate layout files adjusted to what you need. Simply use different qualifiers for the layout folder name according to the docs and the correct one will be used according to the device that loads it.
You can try and adjust one file to work on different screens but you are a lot better off using different layouts if it will be ran on different screen sizes and resolutions.
For example: you can have a default res/layout folder and a res/layout-large to be used on larger screens
I handled this in a fairly ugly way, but it works across all screen sizes now. Basically say the primary image was 800x800 dp (the image view). The buttons would be smaller than this (20x20 dp), however through transparency, i created 800x800 dp imageviews (note: no longer buttons) with everything transparent but the "icon" (still 20x20 dp). Although slightly larger in terms of file size, it's negligible in my case. Now no matter what the size of the screen, the imageviews all stretch the same amount, thus removing any guesswork from using the different pixel densities.
I realize that this wasn't the most graceful solution, but I cannot see any drawback aside from making some of the layout development more difficult, and the image files are slightly larger. I used Paint.NET in order to create the .png's that I used.
I am creating an app that is relevant to me, and that I figured would be easy to implement using some of the core functionality already provided in android. My idea is a simple League of Legends Jungle Timer Application. This is important to know as I link the pictures so people can understand the context.
Note that both images are the same resolution, there is just no border on the second one.
http://i.stack.imgur.com/Ad3LZ.jpg
http://i.stack.imgur.com/NfhRM.png
Additional details:
For this app I have disabled the "landscape" orientation, I plan on doing this using some of the details that were provided on this page (layouts).
All of these icon ImageViews are relative to the map, which is the first link, so they will always resize correctly. There are 12 of them also, if it matters.
Thanks all for your help!
Related
Firstly I wanna say that I red probably all there is on internet on this topic.
I kinda get the picture about it but still I am not sure, and my brain is boiling trying to think about how it should go properly so I need somebody to clarify me these things maybe better than I found at other tutorials and topics.
Also a lot of questions and answers are kinda old and I know that these qualifiers for layouts like small, large and xlarge are kinda deprecated so refreshing would be nice.
So the thing that bothers me is how to support multiple screen sizes and orientations in android?
I understand that I need to support different drawable resources for different screen density's and that I need to use smallest width available qualifier for different screen sizes.
The thing that is the problem and I don't understand is how to accompany both of that together.
For instance for first example I have like logo sign which should draw over the whole screen of the mobile.
Can I actually provide all possible solutions and all possible sizes of that logo in all orientations or the android will size them as needed from the closest ones I give him?
How does the smallest width qualifier go in hand with different density drawable resources?
They just change the size of the picture depending on the screen dpi but they don't change the layout appearance.
Should I change layouts depending on screen sizes, and the pictures will change according to the density by itself what is actually a second example, because like buttons are different story, if they are 50 x 50 px in mdpi they will be 100 x 100 px in xhdpi.
And that's what I kinda get.
The bigger problem is how to put in the picture all alone that is filling the screen by itself and also to take screen rotations and changing of width and height with it in account.
So it was a long question, hope I told you what you need to know, the similar questions have already been asked but they are kinda old and outdated in some parts, and even there I still didn't find all the answers I was looking for so I hope I will find them here.
Looking forward for your help and thank you in advance !
I would say you're over complicating the topic, to support all sizes/layouts, you just have to keep them in mind while designing your layout. A vast majority of your layouts should only need to be built once and if they're built in a way that scales well it'll work out.
For example, if you're trying to draw a splash screen with a logo in the center, you can do something like this.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/my_logo" />
</FrameLayout>
This would work on all devices/sizes/orientations as it is just putting the logo in the center.
When building a layout, just focus on an average size of a current modern phone but keep in mind people have smaller devices. Use that as your base for assets, and try to include smaller ones, or use vector images.
And if you're building a View that is long, wrap it in a ScrollView so it can scroll on smaller devices.
I would only ever use the other layout directories ( for sizing or orientation ) for very specific cases, like when you want to completely change how your layout looks.
Hopefully that helps.
I'm developing a kind of a instructions app. It uses fragments with ScrollvView, vertical LinearLayout and some TextViews / ImageViews in it to explain how a product works.
The images are just simple vector graphics which I save as png due to the lack of vector image support on Android. Here's an example:
The images are always filling the the screen using android:scaleType="fitXY" (portait and landscape) and the scrollviewer takes care of the rest (using android:adjustViewBounds="true"in the image view to prefent from scrolling over the original size of the image).
I read the guidelines of Google to use different versions for the different resolutions and densities but this seems to be overengineered for my purpose.
My idea was to just supply one high-res (2000px width) image of the images in the drawable folder and let Android auto scaling do the rest.
The only issue I can think of is memory. But I'm not quite sure how the internals work here. If an OutOfMemory only occurs when displaying an image it shouldn't be a problem as the autoscaling hits in first.
If the scaler can run into memory issues I'm thinking using 3 versions of the image with different widths (i.e. 800pixel, 1500pixel and 2200pixel) and put them in different resource directories.
This seems not possible though...
The Android Studio wizard for Resource directories has an option for "smallest screen width" but its only for dp (density-independent pixels)! I want a resource file for real device pixels. I hope Android takes the closest fitting and don't fall back to the default one if it can't find an exact match.
My images don't care about density as they are always filling the screen.
So in a nutshell:
Is supplying just one large pixel image with a small file size an issue?
If yes how can I setup device pixel resource directories?
The nature of the app already has an huge amount of images. That's why I don't want to duplicate each a couple of times which x-folds the number of images to deal with. The app is for API 11 onward.
I finally found a solution to proportionally scale one image to device width with no memory issues.
First you have to draw up your image (my_image.png) in a rather high resolution
Put this image ONLY into the drawable-xxhdpi folder.
Extend the Android ImageView class using this awesome answer.
Use it in your layout as shown below:
Here is layout that works for me:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:fillViewport="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/main_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
<my.package.name.DynamicImageView
android:id="#+id/main_image"
android:adjustViewBounds="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/main_text_view"
android:src="#drawable/my_image"
android:scaleType="fitXY"/>
<my.package.name.DynamicImageView
android:id="#+id/main_image2"
android:adjustViewBounds="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/main_image"
android:src="#drawable/my_image"
android:scaleType="fitXY"/>
<TextView
android:id="#+id/main_text_view2"
android:layout_below="#id/main_image2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</RelativeLayout>
</ScrollView>
Some more final information:
I did a lot of testing with point 2 (which folder to put the image in) before I found the solution of point 3.
If you put the image in the standard drawable folder the scaling works without point 3 but you might run into OutOfMemory exceptions on older devices as android tries to scale up the already large image (Android thinks in drawable are only small images without checking their size).
When the image is in the drawable-xxhdpi folder Android knows its high-res and does only a down scaling if necessary. But it doesn't scale the image to width on density fitting devices! For example in a Nexus 10 the image gets drawn in its original size and scale - doesn't matter what you set for scaleType (I reckon it has something to do with inTargetDensity as explained in the inScaled description).
One important thing to keep in mind here is that I have to use a ScollView around the whole content. You may find some other solutions when no ScrollView is involved.
Finally, you could also use the drawable-xxxhdpi folder but it was introduced with API 19. I tried it and it worked on lower APIs as well. Apparently Android build tool 19.1.0 and higher takes care of lower API versions.
I hope this helps someone...
I'm sure there's a basic answer but I'm still learning and I'm not quite sure.
I have an app with a few button on the start screen. It works on a Nexus One (emulator) and a Samsung S2 (device); probably because the screen size is the same. However, when I preview all screens on tablets for example the button are completely spread out and really small. On other devices they're halfway into each other and just doesn't look good. I've tried match_parent and wrap_content but that doesn't help, how do I use some .xml code or layout properties to make sure the button's don't budge into each other yet fill the screen (I'm using relative layout)?! Thank's anyone that can answer.
Is there something in the layout_height/width/align that I could change?
<Button
android:id="#+id/button10"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/button9"
android:layout_alignBottom="#+id/button9"
android:layout_alignRight="#+id/button8"
android:text="Info" />
You need to make seperate layouts for different screen sizes and densities
http://developer.android.com/training/basics/supporting-devices/screens.html
If you set your target SDK version in the Android manifest file to "3", then your layout on large-screen devices will be just a scaled up version of what it is on small-screen devices. Once you set the target SDK to a higher SDK, you can create separate layouts for each screen density, which provides a much better user experience.
However, my layout is mainly made up of images, that are high enough resolution that they display just fine on all screen sizes, even when scaled up, because they're big enough that they don't need to be stretched. Now, it would be much easier for me to just create a small-screen layout and have it scaled up, because it would still look nice on large screens. Is there any way I can get that effect without going back to API level 3?
You can use weight parameter.
“weight” is a term that's used to specify how much of the screen a particular view should occupy if there’s any room left after it’s drawn.
Simply make a LinearLayout and place two TextViews within it as such:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="small"
android:layout_weight="0.2"
android:background="#123" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:text="huge"
android:background="#456"
/>
</LinearLayout>
You will notice how views occupy space accordingly. You can create any layout you want for smaller screen and specify weight attribute and every thing will be adjusted beautifully
Just don't specify a layout for larger screens. By default it uses the same one for all screens unless a more specific layout is available. If you're using match_parent for the width and height and the images to scaleType="fitCenter" or "centerCrop" -- things like that, it should fill whatever screen size that it is run on.
Dont'f forget making your app compaible with tablets. You must add
<supports-screens
android:anyDensity="true"
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:xlargeScreens="true" />
in your app manifest.
Hm. I thought Android already did this as long as you aren't using something like AbsoluteLayout. There's a few tricks that can help with the transition. Not entirely sure what the question is asking, but I'll give it a shot. Does API level 3 scale with aspect ratio or something?
I found that most of the UI ugliness going from phone to tablet deals with width. There's logic you can put in to fix the width at a certain res. Otherwise, the layout looks and acts fine. There other tricks like having assets sized using different dimens.xml, and having different sets of dimens.xml for different screen sizes and densities.
You don't have to have every single dimension in each version. You just have to have the base version of each value set, and you can set the different dimension in the other files.
Only way to resize images through different screen size is to use nine patch. Here is more resource on that subject : http://developer.android.com/tools/help/draw9patch.html
I believe this is only thing that you can do is in layout use relative width/height (weight) and images formatted in ninepath.
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.