Switching Fragments or Activities (ie layouts) on Orientation Change - android

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.

Related

Is it necessary to use fragment in the activity?

Recently learning android-architecture-samples, I found that each activity uses fragment, even if the activity doesn't really need fragments, in my opinion, this makes the activity lazy and leads to a lot of files.
For example, TaskDetailActivity sets the Toolbar, and other view work is given to the TaskDetailFragment.why use a fragment instead of the activity to achieve, you will find that the entire demo is doing this,
I don't think this is a meaningless question. There must be reason to do so.
Can anyone tell me why I wrote this, what are the benefits? Thank you!
No. You can have activity without a fragment.
So why Google and other Android developer advocates are pushing for a single-activity-multiple-fragments architecture?
It's because, this way you can have multiple screens (fragments) share the one single activity which otherwise would be so hard to manage as many number of activities as number of screens in your app. Fragments can easily be added and popped from your activity's fragment backstack so there's a flexibility of sharing resources from a same activity with multiple fragments. Also, if you don't care about differences in the different screens in terms of configuration such as orientation etc. , It's much easier to manage multiple screens in one single container.
From my experience you should create different activities for different workflows. E.g. your whole app (core features of your app) can sit in one activity however other things like sign up, login, onboarding can be activities of their own. This way you can start one single workflow by starting a new activity.
Another good example for choosing activity over a fragment when you are adding a new screen - Your new screen has completely different configuration than other screens (fragments) that are shared within your current activity. E.g. your new screen is a photo / video gallery that requires you to support both the orientations (landscape and portrait) but your other screens in your existing / current activity can only be portrait.
I hope you have a good clarity on why people are leaning toward single-activity-multiple-fragments approach.
There is no rule like that. fragments not must for activity it based on requirement.

Android: After orientation change breaks connection between fragments

Application has two fragments: the first one contains a small representation of pager with photos, and the second one contains full screen pager. The second fragment replaces the first and passes a page number to the previous every time it changes. I made connection between my fragments just like Android Developers says.
Everything works till device orientation doesn't change. The first fragment is not recreated until it is not on top of stack, that is why all page number changes after that are missed for first fragment.
I do not really what to disable views destroy on orientation change, but looks like it is the only way.
What is the best solution?
In your manifest file in your parent activity in which fragments are write following line :
android:configChanges="keyboardHidden|screenSize|orientation"
Let me know if that works for you. Best of luck :)
When you change the orientation, the activity gets rebuild, thus essentially destroying the fragment that was built before the change in orientation.
Perhaps you would wish to refer to this https://developer.android.com/guide/topics/resources/runtime-changes.html on retaining the state during a change in configuration.

Proper way of Fragments implementation in Android

I am developing an app for android lately. I decided to use power of fragments and decided to use dynamic UI. I want to have one fragment included in portrait orientation and two in landscape.
I figured out how to create two layouts and how to add fragments.
Everything is going pretty well until now.
I am trying to find a proper approach to creating and destroying fragments on rotation. I know that I should always check if there is a saved instance, so on rotation there should not be more fragments created. But this solution ignores creating another fragment when user switch from portrait to landscape. So I thought that I need to check orientation before checking if instance was saved. Checking is not the problem but what is the proper way to work with fragments? Should I always create a new fragment and on change rotation remove it? Or have it hidden?
I found one implementation where is activity that have both fragments and when the rotation is changed the new activity was created. But this solution create activity and fragment for one thing and I am not sure if this is proper approach.
What do you suggest? I think fragments are badly covered by official site for android developers.
Maybe this tutorial by Lars Vogel can help you:
Tutorial
He creates a landscape application and shows in chapter 11, how to change to portrait mode.

Compatibility mode and Activity lifecycle

Here are some preconditions:
the app is designed for smartphones (small, medium, large screens)
the app needs to also look so-so on tablets (xlarge screens)
the app needs to give users the option to switch between "Stretch to fill screen" and "Zoom to fill screen" when run on a tablet device.
The thing is - when user switches between these modes, the current Activity restarts => goes through the full lifecycle and I don't want that :)
I know that in case of, ie, rotating the device (going from landscape mode to portrait or vice versa) we can use the android:configChange param in the Manifest to prevent the Activity from restarting. But none of the possible options work in the case of Compatibilty Modes.
Any hints, ideas to NOT have the Activity restart when switching between zoom/stretch would be great :)
I know that this answer does not suit your original problem. But why do you want not to restart the activity? The new activity creation is needed to load (maybe new) resources, adjust width / height etc. You could save the data you need to keep and retain it in the onCreate of your activity. Some ways to retain data are listed on this link:
http://developer.android.com/guide/topics/data/data-storage.html
Maybe it is an option to look at fragments. If you place a fragment inside an activity you could restart the fragment (delete / add) instead of the activity. This way you won't be dealing with the activity life-cycle.

Switch from dual pane to single pane on orientation change maintaining fragment stack

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).

Categories

Resources