I have an application I want to adapt to tablets and handheld devices
When handheld device is in portrait or landscape I want to display ListView and when list item is selected I start another activity.
When tablet device is in portrait - see above.
When tablet device is in landscape I want to display ListView in one part of the screen and selected item content in another part of the screen. Basically something like this:
How should I achieve that? I was thinking different activities and layout resources for each orientation. But I have a feeling that there is a smarter and better way.
Of course I could stuff everything in one activity somehow but it doesn't feel right. Nor looks nice :)
Thank you
What you want to achieve can be done using Fragments. Here is an example depicting the use of Fragments.
To communicate between fragments see this link.
Related
I have to write a simple app which will look different depending on the screen size.
On a small screen it would have a list of items and after click it will display details. On a bigger screen it would have a list of items and details next to it.
My question is: should I use fragments to do such an app or just write different layouts and place them in layout-large or layout-land folders?
If it is a new app I would always go with fragments, basically for future proofing your app. You may have a single list now, but later you may want to introduce a menu for selecting different types of lists for example. By using fragments, on a phone you can use two activities, one for selection, and the other for the list, but on a tablet in landscape mode you can place the selection and list side-by-side.
Coding for possible app enhancements and features now, saves you time and headaches later.
You can do it in both way , but the suggested solution is using fragment
check this out :
https://developer.android.com/training/basics/fragments/fragment-ui.html
and this :
http://www.vogella.com/tutorials/AndroidFragments/article.html
You should use Fragments, since Fragments were created for that purpose, besides, if you make 2 layouts, you will have to do 2 completely diferent layouts and that'll mean that the activity would not handle that, at least not in an easy way, so try fragments to achieve that, the official documentation example is a case like yours, that would be enough to believe that the correct way to do it is with fragments.
I have a problem with switching activities & fragments on certain device sizes, when an orientation change happens. In my case it's large screens, but it could happen with other screen sizes depending on the app. I've looked around for answers, but nothing seems to properly address this.
I have two activities, MainActivity and SubordinateActivity. MainActivity is the only entry point to the app; MainActivity launches SubordinateActivity. Each activity has its own fragment, MainFragment and SubordinateFragment. When running on normal devices, there is only enough space on the screen for one fragment at a time, regardless of the orientation. In that case, each activity will manage its own fragment. On xlarge devices, there is enough space for two fragments, regardless of the orientation. In this case, there are different layout files which allow for two fragments on the screen. Both MainFragment and SubordinateFragment are managed by MainActivity (SubordinateActivity is never used).
The trouble arises with large screens. Using landscape orientation, there's enough space for two fragments, but in portrait orientation there is not. I have the proper layout files for each. In landscape mode, MainActivity manages both fragments (as with xlarge devices) and in portrait mode, each activity manages its own fragment (as with normal devices). This produces problems in two scenarios:
SubordinateActivity is loaded in portrait mode, and the orientation changes to landscape mode. What I want: SubordinateActivity should be discarded and MainActivity should load, with the content previously displayed by SubordinateActivity, displayed in its own SubordinateFragment. Problem: SubordinateActivity stays loaded by itself in landscape mode.
MainActivity is loaded with MainFragment and SubordinateFragment in landscape mode, and the orientation switches to portrait. What I want: The content previously displayed in SubordinateFragment should now be displayed alone by SubordinateActivity. Problem: MainActivity is shown with only the content from MainFragment.
A good example of this problem is the GMail app. Here are some screen shots from that app in case it's not clear what I'm talking about. I realize the UI of the GMail app is actually more complicated than mine, but the problem is the same.
I'm sure that this is a problem others have encountered because the GMail developers encountered it too. I can't figure out what a good solution is, because every possibility seems to involve either violating the Android UI best practices, or creating some ungodly tangle between Activity code and XML layouts.
Here are some ideas I have, none of which seems really correct:
Detect the orientation change in both activities, and launch the other activity (eg, by using FLAG_ACTIVITY_CLEAR_TOP) to go back down the stack and load a previously loaded activity, with a new intent. This is a problem because the orientation change code should only be executed on large devices, which means mingling code that checks which layouts are available with the activity code.
Drop SubordinateActivity altogether. It seems a bit superfluous and MainActivity can manage the fragments itself, even on normal size devices where it can just swap MainFragment and SubordinateFragment as necessary. In the end I don't think this solves the problem since MainActivity still relies on the layout files to tell it which and how many fragments to display. This also would violate the principle that an Activity represents a discrete thing that the user does.
Here are some resources I've been looking at to try to solve this problem. As I said, this seems to be a common problem, but there seems to be no canonical Android solution. This is a bit of a shortcoming since the documentation recommends using Fragments, and every developer who does, is going to run into this problem.
Tasks and Back Stack
How to Controll Android back stack
How to start a new activity when screen orientation changes? Android
onNewIntent() lifecycle and registered listeners
Multi-pane Layouts
Switch from dual pane to single pane on orientation change maintaining fragment stack
android Fragment issue with orientation change
Fragments restore state on orientation changed
Summary: I have the multi-pane mode working for xlarge devices. The problem I'm trying to solve is switching between single pane (portrait) and multi-pane (landscape) mode on large devices that can only handle multiple panes in landscape orientation.
Kill SubordinateActivity and have the only entry point in your application be MainActivity which then decides to either fill the entire viewport with MainFragment or SubordinateFragment. You can find an example on how to do this by looking at the developer docs for the design guide you linked to.
After you do this, you can create a resource folder specific for large and landscape, res/layout/large-land as stated here and set up your layout file for MainActivity to include two fragments similar to lesson #2 in the link from the previous paragraph.
Creating that, alongside your normal XML layouts changing to what's described in that doc should automatically handle everything you're describing since an orientation change is technically an activity re-creation.
I want to know how to chech whether object is existed in layout.
To make clear, I want to check ListView is existed in layout for different screen resolution. If client device is tablet, I'll process for ListView and will make some action. If client device is mobile, I'll ignore this ListView and set visible mode to GONE.
You should define the default (say, phone) layout in /res/layout and the tablet layout in /res/layout-w720dp or something similar. See here for more information on qualifiers for layouts. Then you have defined your different layouting in xml and don't need to jump through hoops in code to make it fit to different screen types.
To know whether object exists or not, just try to find it with findViewById and compare result to null
Disclaimer: This is a link to post on my blog (there is no advertising). I think it might help you think about the way you construct your app to deal with phones vs tablets.
http://damianflannery.wordpress.com/2011/10/16/architecting-a-single-apk-app-to-handle-phones-and-tablets-on-android/
It sounds like your intention is to hide a listView from the screen if the users device is not a tablet. This is easily done using different layouts for different as mentioned in Damians blog post.
However the new correct way of doing this is to use fragments. The basic idea is you combine the code and layout into a fragment and only use the fragment if there is space on the screen. This means that your screen would be formed of 1 fragment if phone and two if tablet, one of which would contain and code for your listView.
Fragments - Android Developer
Currently I have a dual pane layout for both landscape and portrait on a tablet.
Similar to say settings I have a single activity which loads a fragment into the left selection pane and then choices made in whatever right fragment is being shown result in further fragments being displayed into the right pane adding to the backstack all the way.
Now I can see that for some tablets it would make sense to have a single pane for portrait and a dual one for landscape. However, I would want the following behaviour:
A) If in landscape a fragment stack of depth N say is in the right pane then on an orientation change to portrait I would still want fragment N to be displayed and the stack to be maintained
B) Then navigating back from fragment N in portrait mode I eventually want to come back to the selection screen.
Now I can't figure out how to achieve this, ideas that I've come up with thus far are:
1) Have dual panes for both orientations but hide the left one on orientation change, would then need to reshow and hide right pane when stack is cleared
2) Rebuild the stack into the new containter, adding the selection fragment at the beginning on a switch to portrait
Neither, if they work, seem entirely satisfactory to me. Just wondering what the better/recommended way of doing this is.
Thanks in advance. Peter.
Edit 1
It should be mentioned that I understand that you can have have different layouts for portrait and landscape and am finishing up a large project with a dual pane layout for both portrait and landscape so OK on the lifecycle of an orientation change. I have also looked at the FragmentLayoutSupport example but that doesn't maintain the data in the right pane on an orientation change to portrait, it shows the list again.
PJL, so you are on the right track here, either you can check your orientation and then show or hide specific fragments or you can have two different layouts one for Portrait and one for Landscape, in your onCreate function of your Activity you can then check if the second Fragment is available via findViewById and then instantiate it or not. The View you are looking for would just have a FrameLayout with a known Id.
So make sure you understand what happens during an orientation change enter link description here
A really good Fragments Example is part of the Samples of the Book The Busy Coder's Guide To Advanced Android Development the book is part of a 40$ / year description. The Sample code is free though. Check out the Fragments Example it might help with your problems. Also of course you can have a look at the example FragmentLayoutSupport.java on developer.android.com
If you are using the list with action intents and uri's you can reorder the frags depending on orientation, action and uri in onCreate.
If not I guess you can keep a selectedId value in preferences and use it to keep track of your detail-view.
You will have to keep this value up to date by saving it to preferences in onclick and make sure it is updated to -1 (or suitable) on things like back (if back closes this fragment).
I have a tab-based Android app. Currently, it does not support landscape mode - the one and only activity swallows all orientation changes. Now, a user asks that I support landscape for the sake of the hardware keyboard convenience.
On one hand, it makes sense. On the other, the default behavior of a tab host is rotating the tab strip; when it does, it takes a good one third of the precious screen space for the tabs alone. So I lose a lot of real estate.
Are there any common ways out of this conundrum? As far as as I can see, a vertical tab strip is not an option.
I suggest following the technique discussed in Timores's answer to android:orientation="vertical" does not work for TabWidget, where he describes how to set up the TabHost to display the tabs on the left of the screen, with tabs vertically stacked.
Don't use tabs. That's probably the best suggestion anyone can give. Tabs on a mobile devices are a great way to display quick information, and a lot of information. But when it comes to handling user inputs, it doesn't really help considering that it's a mobile device with limited real estate.
While this has already been answered (and I like the one you accepted--will probably implement it myself), there is another option.
Use buttons instead of tabs to navigate between Activities. Each Activity has the same series of buttons in the same locations, much like a navigation bar on web pages.
You can place your buttons however you like, depending on the orientation or however your design sees fit.
For examples, just look at any of the millions of websites with navbars, such at StackOverflow.com at the top of this page.