Android: Tabbed App with Navigation Stacks - android

I'm working to clone an iOS app that uses a UITabBarViewController as the "main/outer/root" UIViewController. Each of its tabs has a UINavigationController as the root to manage a navigation stack of UIViewController instances.
I am trying very hard to do 2 things:
Replicate the functionality of the iOS app.
Do so in true "Android" fashion (i.e., not forcing an iOS paradigm in a non-iOS world).
I've searched around a good bit, but this topic seems to have been changed a lot over the past few years. I tried a solution that had a single Activity that managed everything, but that required maintaining separate back stacks, and seemed to get a thumbs down from most users around here.
Currently, I have a solution that is "sort of" working. As I understand it, my current setup is:
A single, BaseActivity class that extends ActionBarActivity.
All activities in my app (only 2 thus far, but slated for 5) extend this class.
This base activity loads a drawer.xml layout, which has an android:support.v4.widget.DrawerLayout as its outermost item.
Inside of this is:
A FrameLayout, which is the container for my fragments.
A ListView, which is the drawer itself.
Based on my testing of the app, this setup gets me most of what I want.
When I "navigate" (using the drawer) to a different activity, the correct activity is loaded.
When I "navigate" to a "deeper" fragment (via on-screen controls), the correct new fragment is pushed and I've overridden onBackPressed() in BaseActivity to correctly pop the back stack if appropriate.
The problem I'm encountering is this:
The app is launched and "Activity 1:Fragment 1" is displayed. I click on an item to move to "Activity 1:Fragment 2" (which works well).
I use the drawer to launch Activity 2, and "Activity 2:Fragment 1" is shown. So far, so good.
I use the drawer to go return to (at least that's my intention) to the existing Activity 1, and "Activity 1:Fragment 1" is displayed.
I've looked into Activity/Intent launch flags, but I'm not sure I really get what's going on. So far, my reading has led me to try the following steps:
When switching Activites, setting its flag like this:
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
In my AndroidManifest.xml, setting Activity launchMode like this:
android:launchMode="singleInstance", or like this
android:launchMode="singleTop"
An odd, additional problem I'm facing is that launching a new Activity doesn't seem to create the Activity back stack like I expect. When I move from Activity 1 to Activity 2 (ignoring the lack of fragment back stack maintenance for a moment), pressing the back button from Activity 2 closes the app, which confuses me.
Is there a single, current best practice for this type of app structure/navigation?

the good approach is to have 1 activity and handle the back stacks manually as Android has only 1 stack. I've done this several times and finally I created a library called Tab Stacker that does the job: a fragment history for each tab.
It is open source and fully documented, and can be included easily with gradle. You can find the library on github: https://github.com/smart-fun/TabStacker
You can also download the sample app to see that the behaviour corresponds to your needs:
https://play.google.com/apps/testing/fr.arnaudguyon.tabstackerapp
If you have any question don't hesitate to drop a mail.

Related

After navigating with popUpTo, the next fragment shows back button in NavBar

So I have a standard scenario, described in the Android dev docs.
Both fragments are so far pretty much stock from the New | Activity | Basic Activity wizard. I've only slightly changed the first fragment so far to start working on the login credentials.
Basically, after I complete the login, I want to clear my call stack and just move to the main app screen.
This works to some extent for me, by adding:
app:popUpTo="#id/FirstFragment"
app:popUpToInclusive="true"
and then navigating
NavHostFragment
.findNavController(this)
.navigate(R.id.action_FirstFragment_to_SecondFragment);
It works because when pressing the back button / performing the gesture, the app will simply close.
What DOESN'T work, is that now the title bar for the second fragment is showing the back arrow. The back arrow doesn't even work as there's no stack to pop, but still it's there.
I've investigated answers to this question.
I cannot seem to get the FirstFragmentDirections to build, so I can't try that solution. Tried (unsuccessfully) to modify gradle file and searching for a file that would be built, but not accessible.
I am now left with an arrow that has no place where it's rendered and would appreciate any pointers on how to get rid of it.
Edit1: I have now discovered how to get the FragmentDirections class to be generated. It's described here - all the SO suggestions on the matter lacked the repository inclusion and only mentioned the plugin inclusion.
Edit2: The arrow depends on fragment properties. One of such properties is navigation's app:startDestination. It will start the activity on this fragment, but also display the back arrow on all other fragments.
My task has shifted from total non-understanding to seeking how I can specify / override this per-fragment.

Is it a bad practice to have only one Activity in your Android app that uses fragments?

I'm wondering if this is a 'no no' in the Android community.
My app just has a MainActivity and uses a ViewPager and TabLayout to navigate across the fragments in the app.
The only problem I see is if the user presses the back button, it will exit the app and the app will not stay active like it would by pressing the home button.
Your thoughts?
Nice question bro,
Few months back I was thinking in sameway.
You are 100% right, you can do it without any trouble, it only depend on your project and what do you want to achieve.
You could control your fragments from a single activity, beacause all fragments are independent of each other.
The limitation is :
One fragment should never talk directly to another fragment, you have to go through the parent activity
Only some imp points are:
You need to learn all details about fragment.
You have to manage the order of the fragments.
It add lbit complexity in code
One Activity and all other Fragments

Android: Multiple views, deep navigation, one Activity. What is the best way to handle?

I'm looking for the the best way to reproduce, in an Android app, the behavior of the iPhone UiNavigationController within an UITabBarController.
I'm working on this Android app where I have a TabActivity and 4 tabs. I've already gone through a lot of posts regarding the use of activities and tabs and how it's not a good idea to use activities for everything, which seems fair enough. I decided to use one Activity on each tab anyway, since it makes sense in my application.
However, in one of those activities I have a deep navigation tree with more than one branch and up to 12 different views the user can go through.
The problem is: Android controls the navigation through activities inside an app, if you click the back button it will go to the previous one, but if I'm navigating through views, using one Activity, and I click back, it just finishes it. So how can I have a smooth navigation behavior between views in an Activity?
I had implemented this using a TabActivity with FragmentActivity as each tab. Utilizing Fragments API you can organize the code just like you would be using 12 different activities, still using only 1 for each tab in fact. Fragment's framework will handle back key press for you to show previous fragment instead of closing the entire activity.
There are some problems with such approach, for example, there's no MapFragment, but the workarounds can be found here on SOF.
You will need Android Support Package if your minimum SDK version is lower than 3.0.
Well I know very little about UiNavigationViewController, but I guess you want something to navigate between different Views. As you are using TabActivity, every tab should load into a separate Activity.
But since you want to branch it out, using that many Activities is not a perfect solution, neither the ActivityGroup too. The better solution, as per my opinion(I have run into similar problem once) is to have the main or root tabs loads into separate Activity, but for their branches, use the ViewFlipper, which flips the Views. So the whole Layout(Subclass of View) can be flipped.
You may run into some problem while flipping more than two Views (as what people say, though I never had any problem). So in that case you can use layout.setVisibility(View.GONE) to hide the layout and just change it with View.VISIBLE for next view.
And about the concerns of back button, you need to store the last used View or Activity into a variable, and in the override of onBackPressed(), just need to call them.
There might be better solution than this, not that I can remember, but yeah it's the easiest solution I can come up with.

How to manage multiple Activity stacks in an Android app, like you would on iOS with multiple UINavigationControllers within a UITabBarController?

A fairly common model for iOS apps seems to have a single UITabBarController, where each tab essentially holds a UINavigationController, i.e. a stack of controllers, and pressing a tab switches to the top of the corresponding stack. Can I get the same behavior on Android without a lot of custom code? (Note: I am using menus instead of tabs on Android).
After reading http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html the closest I can see is to have multiple tasks, each one representing a stack (akin to UINavigationController), and to use FLAG_ACTIVITY_NEW_TASK to switch to another task/stack. When I switch, is there a way to go straight to the top of the stack, or do I need to keep that piece of state myself?
One problem with keeping that state myself: I've noticed that if my app launches an Intent that starts a new process, sometimes my original app's process is killed (I think), and all of my global state is destroyed.
The only other solution I can imagine is to have a dummy Activity per stack, to push DummyActivityN essentially right before I switch away from the Nth stack, and, when switching to the Mth stack, to start activity DummyActivityM with FLAG_ACTIVITY_NEW_TASK, and then have DummyActivityM immediately finish() itself.
One last problem: as I navigate to the bottom of one of the stacks, with the back button, I would like to hit the back button once more and NOT go to another stack/task. But this seems easy to overcome by launching an Intent to go to the home screen; is there anything better?
If I understood your problem correctly, if you add this parameter to your Activity declarations in AndroidManifest.xml, the Activities that are launched by your custom menu will be only created once - keeping their state while you move around the tabs.
android:launchMode="singleTask"
I hope this helps,
Best,
-sekran

Modifying application workflow to use TabActivity

This question actually has two parts.
The first part:
I've been developing my first app for a couple of weeks now. I have 5 screens and everything seems well. However, I'm considering changing the app's navigation to a TabView.
I haven't delved much into it, but I'm hoping someone can save me a little bit of time. It seems that people don't generally place Activities inside each tab. They simply point the tab content to a View. This is where my major setbacks are. 1) I already have Activity classes full of code and 2) I can't quickly guess how the structure of an app using TabView looks. For example, where do I put the handler code for clicking a button on a View? Does it all just get dumped into the TabView Activity somehow?
What I would like is if you could please give me a quick synopsis of what I'm looking at doing, answers to any questions you think I may have, and point me toward some resources for creating TabView applications. A quick Google search really just shows me how to create a TabView Activity and add a couple tabs to it. The code doesn't go any deeper. For example, say I have a layout xml to show in one of my tab's content pane, where does the code go for clicking a button I have in that layout?
The second part:
I've added a TabActivity to wrap the Activities I currently have in. At the moment I have Activities populating the content of my tabs (though ultimately I'd like to do this in the most efficient fashion, which doesn't seem to be having Activities be tab content). I've noticed something rather annoying. My MAIN Activity is an Activity I wrote for my user to log in to their account. After logging in, they are taken to my Tab Activity. Here is what happens:
When I am on my Tab Activity and I "minimize" the app by clicking the Home button and then launch it again, I don't get taken back to the Tab Activity. I get taken to my log in Activity. Why? I don't have the launchMode of my Tab Activity set to singleInstance... or is it singleInstance by default? How can I make the app re-launch showing the Tab Activity (ideally by setting some parameter, assuming I'm doing something wrong, and not having to save this data off somewhere and reading it and programmatically telling it what to go to)?
Thank you for all your time and help
I don't have a comment on the advisability avoiding the use of sub-activities in TabActivity. As for handlers -- if you aren't going to embed views instead of activities, then all the android:onclick type handler settings in your layout XML will call methods on the TabActivity. This is because they go to methods on the views' Context, which is the generally the nearest containing Activity. If you want to split your code up further without using Activities, I believe you'll have to use findViewById calls on the tab content views after you've set them up, and bind the handlers manually from there in your code.

Categories

Resources