When making apps for Android 3.x, you could basically just check if the device was in landscape to see if it could fit multiple fragments side by side. But this is only because you were basically guaranteed that the device is a tablet.
With the introduction of the compatibility library and android 4.0, I can't think of what I would consider as a 'good' way to determine if I can get away with side by side fragments or should revert to standard one fragment per 'screen.'
In the NewsReader example app, Google has a special values file for every common resolution, each with a Boolean value for whether the resolution should support the 2 fragment layout, but I think this way is poorly conceived. The only way I can think of is to check the size of the screen (to guess if it is a tablet or at least big enough to not ruin the layout), and then check the orientation.
So if anyone out there has an idea how to easily and efficiently check this, please let me know!
You can actually see the screen size type (small, normal, large, etc) by using the following:
getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK
That'll return an int that you can check against any of the following:
Configuration.SCREENLAYOUT_SIZE_SMALL
Configuration.SCREENLAYOUT_SIZE_NORMAL
Configuration.SCREENLAYOUT_SIZE_LARGE
Configuration.SCREENLAYOUT_SIZE_UNDEFINED
Then you can check for orientation, using
getResources().getConfiguration().orientation
Which will match any of the following possibilities
Configuration.ORIENTATION_PORTRAIT
Configuration.ORIENTATION_LANDSCAPE
Configuration.ORIENTATION_SQUARE
Configuration.ORIENTATION_UNDEFINED
With this you can essentially simulate the multiple views by adding your fragments as space allows based on screen size and orientation.
I create 2 layouts, one with one container (ViewGroup) for a fragment, and the second layout has 2 containers side by side. I use Android's folder structure for resources to specify that the scenarios where I want the multi-fragment (2 container) layout. Then in code, check for the existence of the second container to determine if you are multi-panel or not.
isMultipanel = false;
ViewGroup container2 = findViewById(R.id.container_2);
if (container2 != null) {
isMultipanel = true;
}
Try not to think of it as tablet or phone, but rather wide enough or not wide enough for 2 panels.
If I wanted multi-panel on normal size devices (<= 5") and large (5" - 7") only when they are in landscape, but always on xlarge (> 7"), I would put the multi-panel layout file in:
layout-land
layout-large-land
layout-xlarge
Then you don't have to do size checks in code since Android is already handling this for you.
Related
I am getting very confused on how to support all different Android screen sizes. I have already checked this answer, this site, the official documentations and many other answers but still I am confused so please don't mark this as Duplicate.
I already created layout-sw120dp, layout-sw160dp, layout-sw240dp, layout-sw320dp, layout-sw480dp (I only need to support up to 6 inches so I don't create layout-sw600dp).
What do I have to do is just have one layout and just copy it in each different folder so Android will do the selection on its own or I also need to change values in each layout?
What do I have to do is just have one layout and just copy it in each different folder or I also need to change values in each layout?
You start by deleting the layout-sw120dp, layout-sw160dp, layout-sw240dp, layout-sw320dp, and layout-sw480dp directories that you created. Or, at least, ignore them for now.
You then start implementing your UI, putting layout resources in res/layout/.
Then, for those layouts that need to be different in certain scenarios, you then create a directory representing the size when you want a different layout. Copy the layout from res/layout/ into the new directory, and then modify that copy to reflect whatever changes you want.
In other words, one copy of every layout is in res/layout/, and you override where needed with additional, modified copies in specific directories where you need the UI to change.
If you want to use the same layout for each and every screen density, you don't need to create different folders. Use just one simply called "layout" and the system will interpret it for every density. However, this could lead to strange layouts on certain physical devices depending on their screen size and density...
Another point you have to be aware of, if your application supports orientation changes, is that you have to design layouts for portrait and lanscape orientations. This is done by duplicating a folder used for a density and add "-port" or "-land" to inform the systen which one must be used according to the actual orientation of the device your app is currently running on.
If you want to precisely define your app look and feel, you have to customize your layout for each density. And if you use bitmaps, you will have to customize them either (for example, your app icon should be defined with different sizes to keep a good looking for each screen density). Just as for the layout, you have to create "drawable-..." folders to contain the corresponding versions of your bitmaps.
This is an answer that's been an issue from old ages and for which you'll see lot many answers but which is not a one fit all type still. What I did come up with though when faced with the same issue was to use PercentRelativeLayout. This is a relatively new feature that was started from Android support version 23.0 (android sdk manager), and one of the big game changers according to me, since it allowed
developers to specify their blocks relative to the layout size Percentage-wise. And since it is in terms of percent, this fits all screen sizes with varying dimensions, but while maintaining the ratio.
Ofcourse this method involves some trial and error and a lot of experimenting, but I found this method to be the easiest to implement and which took out the headache of maintaining the dimensions for various screen sizes.
Few tutorials to get you started :
https://www.tutorialspoint.com/android/android_relative_layout.htm
https://guides.codepath.com/android/Constructing-View-Layouts
I'm aware that I can set different layouts for different screen sizes, but I would like to pull out the information of which one it has chosen. For example in the activity layout file for large tablets, I would like to add a view that scrolls through different statistical stuff, but on smaller phones this won't look good, and I'd rather have nothing there, as this will be a menu (i.e. fragments are overkill and will distract from the actual purpose)
So I would like to write some code which says something like:
if(xlarge) {
(manipulate stuff)
}
Is it possible to pull out the right constants from somewhere?
In your code, use findViewById to get a reference to the View that exists only in your large screen layout. If that reference == null then you know you are working with your small screen layout otherwise you know you've gotten hold of the large screen version.
If you really don't want to use Fragments for this, check out these links:
https://developer.android.com/reference/android/view/Display.html
https://developer.android.com/reference/android/util/DisplayMetrics.html
You could use the device's size like this:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
if (heightPixels > MIN_HEIGHT && widthPixels > MIN_WIDTH) {
manipulate stuff...
}
EDIT:
Just saw your comment to the original question. To get the screen size category, this question seems to answer it:
How to determine device screen size category (small, normal, large, xlarge) using code?
I am building an Android app and for large screens I want to populate a 6x6 grid with images; on smaller screens I want to populate a 4x4 grid. My problem is that, in code, I need to know if the screen is layout-large or bigger - to populate the grid appropriately.
So, how can I tell if Android is selecting layout-large or not?
Well you might consider setting things up so that your grid just fills up regardless of size, but short answer:
getResources().getConfiguration().isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE);
Note that the above API call is for Honeycomb or newer. If you're targeting older than that you'll have to use:
getResources().getConfiguration().screenLayout == Configuration.SCREENLAYOUT_LARGE;
See the docs on Configuration for more.
I am currently writing a remote control program to control a robot on all android devices.
I am trying to display the layout to fill the screen fully on different sizes. My first try was on a samsung 10.1' tablet and it was working well but when I port it to smaller devices like 4.3' the layout goes wrong. I am thinking of creating several layouts to match with different screen sizes but how do I check which layout to set according to screen sizes?
I have tried getwidth and getheight but it only works after you have set the layout.
Please give me a short sample code if possible as I am very new to this.
If there are any other better ways please advice me on it.
Please note that I am using API level 8, android 2.2.
Go through this and this. Basically, you create layout for various screen, each with same name. They are put in different folders (each named according to factors like- landscape, portrait, screen density and screen size). OS will decide on it's own about which layout to use.
This is great article about that. But in overall, never expect the screen to be any static size. But if you're deciding to create layout for each size, you don't have to worry about choosing the best layout, android will do it for you if you provide multiple versions of same layout.
You do not have to check the screen dimensions. Just create your layouts, and Android will automatically pick the correct one for your screen size, orientation, API level, etc. See here for more details: http://developer.android.com/guide/practices/screens_support.html
I've search a lot and don't find the right information for that. I have 2 different activities in my project. At start it was 2 different application, one for mobile and one for tablet. I want to mixe them to get one APK only. So when they where separate it was easy, but mixing the 2 manifest i not for me.I would like to be able to have 2 different activity and the right one launch if this is a mobile and the other if it is a tablet.
Anybody have an example of a manifest that can do it?
To Extend slayton's answer, in the splash (or launcher activity with no interface), you will need to detect whether it is a tablet. You will need to make you're own determination what is considered a tablet. I assume that you are thinking of screen size. Here is a simple example that I got from here: http://groups.google.com/group/android-developers/browse_thread/thread/d6323d81f226f93f
It uses the magic screen size > 6 inches to determine it is a tablet.
public boolean isTablet() {
try {
// Compute screen size
DisplayMetrics dm = context.getResources().getDisplayMetrics();
float screenWidth = dm.widthPixels / dm.xdpi;
float screenHeight = dm.heightPixels / dm.ydpi;
double size = Math.sqrt(Math.pow(screenWidth, 2) +
Math.pow(screenHeight, 2));
// Tablet devices should have a screen size greater than 6 inches
return size >= 6;
} catch(Throwable t) {
Log.error(TAG_LOG, "Failed to compute screen size", t);
return false;
}
Once the launcher activity determines it is a tablet or not, just launch the appropriate activity.
Lets say you currently have two activities, PhoneActivity and TabletActivity. Create a third activity called SplashActivity. Think of SplashActivity as a splash screen or launcher that is only running for a split second. When your app is launched SplashActivity launches, detects if the device is a phone or tablet and then launches the appropriate activity (PhoneActivity or TabletActivity).
This entry is now old but I've not found the question elsewhere on this site, and I think the advice is probably no longer true - arguably it was not the best even then, but that might not have been apparent.
The best advice is probably in:
https://developer.android.com/guide/practices/tablets-and-handsets.html
although that is not always clear. I had a similar problem: I've an application that lists some entries (they are dates) and if you click on the dates the phone behaviour is that it switches to a new screen with info for those dates. [OK simplification, but hopefully you get the idea]. The "new screen" is a new activity. I wanted to set the tablet behaviour so that the "new screen" bit was shown to the right or below the list of dates - you'd always see it.
Both activities had been written as standard - without using frameworks. The main change I had to do was to restructure the DetailActivity as a Framework - with a very thin Activity around it. If I'd followed the linked guidelines, I would also have restructured the MainActivity similarly, but so I've not - there is seemingly no actual need to. Instead I've rewritten the MainActivity to handle whether the DetailFragment is present or not - e.g. when you click on the dates, it either updates the fragment directly or creates an intent to open the DetailActivity. The key part of this is the statement:
mDetailFragment = (DetailFragment) getSupportFragmentManager().findFragmentById(R.id.frag_detail);
which goes in the activity's onCreate() method, after SetContentView(). Key here if the fragment does not exist in the layout, then null is returned - there are then several places in the subsequent code along the lines of "if (mDetailFragment != null)".
With that it is merely a matter of having different layouts for tablets. The now advised approach here is to go on the Smallest Screen Width, so using layout directory layout-sw600dp for the tablet version. Actually in my usecase, I wanted different layouts for landscape (detail to right) and portrait (detail below), so I had separate layout-sw600dp-land and layout-sw600dp-port versions of the main activity layout file.
One knock on from this, and if there is an issue with this approach then this is it, is that other layout files may also need to be duplicated. For example, the layout of the existing DetailsActivity already has different portrait and landscape versions - optimising the screen space. It turns out that if you put the details on the right on a tablet, then the screen space needs the portrait orientation - the space is higher than it is wider. At least that is true for my use. Similarly, the fragment's space when the tablet is held portrait is naturally landscape in shape. To get around this, I copy the fragment_detail.xml file from layout-land to layout-sw600dp-port. If I change one of these files, I have to change both. It would be nice not to have to!