I have an app that is using a DrawerLayout and each item in the drawer will load a Fragment. The structure looks like:
News -> News Story
Photos -> Gallery -> Photo
Events -> Event
Directory -> User Type -> User Profile
Each top level is an item in the Drawer, tapping one will take you to that fragment and you can go deeper into that section by adding additional fragments on the stack, e.g. navigating from Photos to a Gallery to a photo in that gallery.
It gets confusing when I need to manage the navigation of each of these sections as individual stacks. On iOS I would use a UINavigationController for each section so that I could manage either separately. But on Android I am not sure how to do this. It is almost like I need to have multiple Fragment Manager instances. Without this, I feel I will run into issues when:
A user is deep into the News stack then switches to Photos, they navigate deep into that stack, but want to return to where they were in the News section. How can they return to that stack? And, navigate back up the News stack?
This seems like a major design issue with Android, unless I am missing something. Any ideas on how to solve this?
EDIT:
Basically I want what they showed at Google I/O:
https://www.youtube.com/watch?v=XpqyiBR0lJ4
I just built an app with this design. I just kept adding fragments to the stack when the user was in 'News' or any sub category of 'News'. If the user navigated to 'Photos' I would just pop all of the fragments from stack with:
getFragmentManager().popBackStackImmediate(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);
and start adding to the stack again. I'm not sure if this is the 'right way' but it worked fine for me. I would just log the last fragment they were viewing in 'News' and restore it when they return to 'News' if that's the behavior you are looking for.
I managed multiple categories/sub-cats just fine using one Activity.
Related
I'm programming deep link behavior where a particular link navigates the user to a video. In the normal flow, the user navigates to this video through a course details fragment containing a list of the videos.
However, the deep link flow obviously skips this screen, meaning that when the user backs out of the video, they are sent directly to home. I'd like to insert the course details screen into the backstack so that when the user backs out of the video, they are instead redirected to the course detail screen. What is the best way of doing this?
At the moment, my deep link code executes a navigation to course details screen right before the navigation to the video occurs.
You can make transaction fragments easier by using the following class (which is done with 4 methods in total) For more readability and simplified transaction.
https://github.com/mahditavakoli1312/FragmentTransaction---mahdi-tavakoli
I have two urls which falls under the same deep link like below :
xxx.yyy.zzz/pages
xxx.yyy.zzz/how-deeplinks-work-exactly
Now the first one is a list of pages which goes to a fragment which lists the list of pages and second goes to a fragment which shows the details of that page.
Scenario :
https://github.com/android/architecture-components-samples/tree/master/NavigationAdvancedSample
I am following the above sample for having independent stacks for each tab.
When I have two different deep links for the above two links, it navigates to both the fragments. Like when I open the app with xxx.yyy.zzz/pages url it opens both the PagesFragment and DetailFragment one after another. So when I press back button from PagesFragment it navigates back to DetailFragment.
Now how do I handle these two scenario with deep links. If have both the deep links setup it navigates to both the screens one by one. I know I can change the path and add a prefix the page detail url(xxx.yyy.zzz/page/how-deeplinks-work-exactly), but is there anyway I can intercept the parsing logic or add some exclude condition to achieve this without changing the url scheme?
Edit : This is likely an issue with the Navigation logic (NavigationExtensions.kt) written for having individual stack.
You shouldn't use NavigationExtensions.kt anymore, instead increase your navigation component library version. Check this article out: https://medium.com/androiddevelopers/navigation-multiple-back-stacks-6c67ba41952f
Perhaps upgrading the lib version also changes the behaviour of your app with respect to the deep links
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
I have seen a few questions raised on this topic (for e.g.: https://github.com/jfeinstein10/SlidingMenu/issues/5) but I am still unclear. I hope somebody can clarify this.
Context:
See https://github.com/jfeinstein10/SlidingMenu
I have an android app that organizes screens by activities and fragments (i.e.) each screen is an activity containing one or more fragments.
The new requirement is to add a sliding menu (similar to what this library provides).
Issue:
It appears from the examples and discussion that the right model would be to have just 1 MAIN ACTIVITY that will then switch in/out fragments belonging to the different screens. In fact the author mentions in the above thread: "If you were to launch Activities based upon the list selection, then you would not have the behavior where you swap the views that you're talking about. " and also "You can't put an Activity into the above view. That doesn't really make sense when you think about what an Activity is. ".
Why doesn't it make sense? Obviously, I am missing the point here.
Question:
Given that my project already contains multiple activities (one corresponding to each screen), is my only option then to re-organize the project to have JUST 1 MAIN ACTIVITY, in order to use this library? Or alternatively, is there any way to launch a new activity when a list item in the sliding menu is clicked, and still observe the sliding menu behavior, [EDIT- added the last part to be more clear] or in other words, on how exactly to use this library within my existing app design.
Thanks in advance
First, you can't have an Activity inside another and activities are completely different from views as stated in the docs:
An activity is a single, focused thing that the user can do.
Now, to answer your question, it all depends on how you want your app to behave. You could have your activities with the sliding menu implement the onClosedListener and switch to the selected activity from there. This will give you the animation of closing the menu before switching activities. It will also give you a weird effect since every time you select something from your menu you'll see the animation of a new activity coming to the front.
I think the best approach would be to have a "common purpose" between all your sliding menu options. For example, in one of my projects I have to allow the users to select between lists of different types of data. When the user selects anything from the menu, I load a new list fragment into the right corner where he may choose the item he wants to view or edit. That's the app entry point and also the only place were I have a sliding menu in my app. It is pretty much the same for every app that implements this UI design pattern. Look at google+, currents and youtube where the side menu lets you choose which feed or content to show. Once a user makes a selection, just open a new activity for the selected item (a g+ post, a video, a news article, a tweet or whatever it is).
Your app doesn't have to have lists of different data or anything like that to use the sliding menu, but keep in mind that the activity with the sliding menu should have a clear, focused goal with respect to its functionality and purpose. Having a sliding menu because many other apps have one is a bad choice, you should use it with a specific objective. Also keep in mind that applying the sliding menu everywhere would interfere with the platform's navigation pattern and lead to an overall bad user experience since it wouldn't behave as the other apps.
It doesn't make sense to place an Activity into the above view because the Activity is the main controller for the view of each screen. The Activity also shows views and keeps track of Fragments (which in turn are mini controllers, with or without their own views). So placing an Activity in the above view would mean that you would place an Activity in an Activity... Wich is impossible.
From what I can derive from your text I think it would be wise to read through the Android developer guide on Activities and Fragment again (http://developer.android.com/guide/components/activities.html) to get a better understanding of how the concept of Android works.
Now to your question:
I am not clear on what you are trying to achieve but if you want your app, with menu to behave like, say, the Google+ app then one way of doing it is to implement a base class that extends the Activity class (or what ever base Activity used in your project) and let the base set the SlidingMenu. Then you would simple extend your base Activity in each of the Activities that are supposed to have a menu.
You could also do it the way you describe it, but then you would end up with a classic example of a God object (http://en.wikipedia.org/wiki/God_object). It's a neat way to practice your Fragment juggling skills and switching between Fragments instead of starting new Activities does have it's use cases, but I still wouldn't recommend it for a project with more then a few views.
Here is the answer that came closest to the issue I had - http://www.verious.com/article/polishing-the-sliding-app-menu/. Scroll down to the bottom of the page to see the last section titled "Using the fly-in app menu between Activities". This is one option if you have a lot of activities in your existing app and want to avoid extensive re-factoring. I haven't tried this out yet but its worth being aware of.
I'm trying to work out the best way to implement the 'ancestral' and 'temporal' navigation (utilising the up button and back buttons), for a music player I'm working on.
Currently, the user is presented with a viewpager, and can page between three main fragments (ArtistMain, AlbumMain and SongMain). Upon choosing an item inside that view, a fragment transaction occurs, and the viewpager goes out of view, replaced by a new fragment (AlbumSub, Songsub or player, depending on where the user came from). The user can then navigate deeper, until a song is chosen, and then they are taken to the 'player' screen.
I guess the question is: How do I implement all of this conditional navigation?
I'm fairly new to android and programming in general, and I just can't seem to come up with an efficient way to achieve this. At the moment, as each fragment is brought into view, the app is checking to see where the user just came from, and then determines where the user should be taken if back or home is called. This means I have a booleans like "fromArtistMain", "fromAlbumSub", and I'm checking for things like "fromSongSub && fromPlayer".. it's all turning into a bit of a mess.
I've drawn a diagram (in paint, sorry!!), to depict the navigation I'm trying to achieve. The yellow represents the 'up' button press, the red is the 'back' button press, and blue is just normal navigation. The green arrows are meant to represent the view paging:
Any advice is welcome. It might take something really simple that I've just overlooked.
Thanks for your time.
Edit:
I have been adding fragments to the backstack, and using popBackStack() calls, the problem is that popping the backstack is not necessarily the correct option in each case.
I've currently got a whole mess of code trying to determine whether a transaction should be added to the backstack in the first place.
Consider the following:
User chooses a song straight from 'SongMain', and is taken to 'Player'. Now using the home button should (in my mind), take the user to SongSub (the list of songs from the album that the chosen song belongs to). Now if the user navigates up again, they will be taken to 'AlbumSub', the list of Albums by that artist. This is a fragment transaction, but adding to the backstack would mean the user would be taken down a level on back press (which I think would be unexpected). So in this case I don't add that particular transaction to the backstack - seems fine, but there are quite a few different cases, and combined with a viewpager at the top which needs to come in and out of visibility, the code gets really messy.
All of this means a whole bunch of conditionals determining where the user came from and which path they took to get there..
Would it be wise to have a bunch of booleans in the host activity which get set depending on where the user has navigated, and then checking those booleans to see if a transaction should be added tot he backstack? This is kind of what I already have, but it seems really inefficient.
What you're looking into is called the Back stack. You can read more about it here at developer.android.com.
If you use a single Activity to host each of these Fragments then you can modify your code to explicity add your Fragments to the Fragment Back stack using code like so:
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container, fragment);
transaction.addToBackStack("NameOfFragment");
transaction.commit();
So, if you do the above code with Fragments like so:
Fragment1 -> Fragment2 -> Fragment3 -> Fragment4
Then from Fragment4 if you call this method:
getSupportFragmentManager().popBackStackImmediate();
Then Fragment4 will be finished and Fragment3 will restart. Simple. You can have this line called from a button click or you can override the behaviour of the back button to call it.
Please note in the examples I've used the function getSupportFragmentManager() which is a method name in the Compatibility Package. If you're not using the Compatibility Package then you can instead call getFragmentManager().
EDIT
The problem with the navigation you envisage is that breaking out of the backstack paradigm half way through means that your app will "Act Differently" than the rest of the OS. This is by and large discouraged by Google. But then again, saying that, I do exactly the same in my app for very similar reasons :).
When you navigate "up", along one of your yellow lines, you are following a discrete link (so, startActivity(new Intent(this, SongSub)); or whatever) and you want this to "break" the backstack.
It's at this stage you can make a decision about how you want to go forward:
You can start a Task (backstack) using SongSub as 0th item. This is from memory what the Google Music app does and you're right, it's annoying. When you press back it should technically exit the app. Yuk. IMO if you're in an obvious page hierarchy, back should always navigate down the hierarchy over exiting the app.
You can start a new Task using ArtistMain as the 0th element and layer fragments discretely ontop before commiting your transaction, in effect creating a new backstack each time you go "up" rather than "back" (your backstack would now be ArtistMain->ArtistSub->SongSub). This is what I think your trying to ask here. It's possible but it's messy.
You can create a more linear structure (probably the best idea if possible). Ignore the backstack paradigm, make "back" and "up" always go up a level no matter where you came from (Player always goes to SongSub, SongSub always goes to AlbumSub). This will give the user the least confusing and most transparent (as well as easiest to implement) experience - the user will learn quickly how to navigate (and how many "backs" to press) to get to where they want to be.