What is the best way to implement bottom navigation between activities that reside in different packages ? Where the packages import one another in a top down fashion.
Setup
I have structured my project as a set of packages; Essentially split into the main app, a number of intermediate PACKAGEs and the final end package :
app - Provides the main application and serves as the projects build target. It contains a single activity, Main, providing the primary entry point for the application. The navigation graph simply maps the only fragment to the ACTIVITY's provided by each of the imported PACKAGE's.
PACKAGE - Provides a single activity, ACTIVITY, to manage a dedicated task. The navigation graph manages the relationships between the various fragments supporting the activity; Additionally it includes link to the Final activity imported from end.
end - Provides a single activity, Final, which each PACKAGE importing it uses as the terminating navigation link for their navigation graphs.
So each package contains a single activity, one or more fragments and a navigation graph that manages the routing between them and a node pointing to the activity in the next package in the order app.Main > PACKAGE.ACTIVITY > end.Final.
Navigation
Given this structure I want to add bottom navigation, |Main|...|Final|, to each activity ACTIVITY such that there is a link back to Main and another onward to Final. Linking forward to Final is easy enough as enough as it's already a target in each PACKAGEs navigation graph but I am uncertain on the best method for linking back to Main. Similarly I want to provide bottom navigation, |Main|ACTIVITY|...|, to Final such that the user go back to either the preceding ACTIVITY or Main.
Considerations
What is the best means of providing navigation targets to the activities in the parent packages ? To me the following seem viable
Cross import all of the packages within gradle. That is app imports each PACKAGE and end, every PACKAGE imports both app and end, and end imports each PACKAGE and app. This is not very DRY but it will make all activities universally accessible.
Pass Main as a list to ACTIVITY, adding it to the navigation menu programatically. Similarly pass Main and ACTIVITY as a list to Final. Here I'm not sure, given that activites have lifecycles, if I should pass the activity class or the instance thereof to the child activity ? The advantage here is that I can readily create the backstack if it's missing.
Interrogate the "Activity" back stack as it already details the route to both ACTIVITY (That is it contains Main) and Final (That is it contains Main and ACTIVITY). Here it becomes tricky to create the backstack after the fact.
Use deep linking ? (I'm still reading up on this)
Should one simply cross reference each activity setting parentAttribute under the <activity/> in each PACKAGES's manifest.xml to provide the necessary navigation targets ? Here I'm not sure how best to add this to the bottom navigation graph/menu ? Also it becomes necessary to programmatically set the parentAttrbiute depending upon the route taken to reach Final.
Depending on how access to the activities is provided in 1 I'm not sure what the best means is of making such target accessible ?
Can this be done within a navigation graph ? Can I programmatically add activities from a parent package to the navigation graph ? Can a Placeholder be used to reference such items ? Can a custom navigation destination can be written to represent such items.
Should one simply populate the menu provided to the navigation menu used by BottomNavigationView ? Can one do this and support targets provided by a navigation graph, that is can one overwrite both OnNavigationItemSelectedLsitener and use setupWithNavController together ?
Note : While I have seen some similar questions and answers I haven't seen any that deal with activities in separate packages.
I solved this problem by interrogating the package manager to determine the activities that are available within my application, under my package name.
Adding metadata to each activity, under the MANIFEST.xml, allowed me to filter the activities I wanted to reference. Adding android:label and android:icon attributes allowed me to provide labels and icons for the buttons in the navigation view and to display them upon the app bar. Furthermore I could create intents for each activity and set these upon the menu items (One of the android docs mentioned that any menuItem that is not handled directly will have its intent attribute invoked).
I wrapped all of this into an interface and can now tack that onto the activities I wish to navigate too outside of the navigation graphs supported by the navigation components.
Note : It's possible deep links serve this purpose but I haven't seena nice example just yet.
Related
The new android navigation component is what seems to be recommended. Im follow the official tutorial on graph nesting.
To group destinations into a nested graph, do the following:
In the Navigation Editor, press and hold the Shift key, and click on
the destinations you want to include in the nested graph. Right-click
to open the context menu, and select Move to Nested Graph > New Graph.
The destinations are enclosed in a nested graph. Figure 2 shows a
nested graph in the Navigation Editor:
Everything works well so far, I just have one issue.
The nested graphs are all part of one big xml file, this is an issue because it can lead to merge conflicts when using source control.
So my question is can we have this same functionality if we simply create two navigation graphs and include the new graph as a destination?
Will everything work as expected or would there be unintended consequences to doing this.
For example poping back to the root of navigation controller? I'm not very familiar with Android but my fear is that a new navigation controller is created and I cannot easily navigate when having two navigation graphs.
Nothing in the tutorial seems to mention this.
As per the Reference other navigation graphs with <include>:
While this is functionally the same as using a nested graph, include lets you use graphs from other project modules or from library projects
An <include> is expanded at runtime to function identically to a nested graph - there is no difference in what you can do regarding popping up to other destinations, etc.
However note that Safe Args does not work across separate navigation graph files (as you could include that graph in multiple other graphs, so there's no guarantee that anything outside of that file actually 'safely' exists), so you would need to confirm that any use of Safe Args is within a single file (using other mechanisms, such as manually navigating or navigating by deep link to navigate to graphs you know exist, but cannot be verified at compile time).
We have an Android application made of menu of modules and each module has the same layout as on this picture:
You have a header with module name and two buttons on the bottom. The module itself is behind those three transparent elements. Left button allows the user to move to the previous screen and right button gets him back to the menu with modules. Text in header changes based on current screen action.
My question is how to build the module transparent frame. Is it possible to have one layout in Android on top of the other? Should we design the code as a parent class that would be inherited by all the modules? I am interested in some best practice. I have experience with Java but only theoretical knowledge of Android.
Prepare a separate common layout and use to add that layout to as many layouts you want.
for more details check this
What you are looking for are so called Fragments. These Fragments are sort of like Activities, with their own layouts and lifecycles, but you are able to use multiple Fragments at once. This means you'll be able to use one Fragment for your navigation and header, and one for the module behind it.
I have an existing app that is using a Dashboard style pattern where there's a main menu, and clicking icons on the main menu drive start different activities... In order to navigate to a different function, you need to go back to the Dashboard menu and select another icon.
I want to change my application to a tabbed format similar to the one below with Icons:
What type of View is being used below? Is this a FragmentActivity? Also, what is the best approach to go about conversion? I have a bunch of layouts with listviews in linear/relative layouts... Will I be able to reuse any existing code? I want also to be able to use the solution with Android 2.1 and up if possible.
Thanks!
In the image you provided, it looks to be a TabHost that is used (which can be within a normal Activity or a Fragment Activity) and will be available for Android 2.1 and beyond when using the Android Support library. Based upon your description, you most likely have an Activity per each of your items that you will probably want to convert into a different Fragment. This may take a little time, but a Fragment is very similar to a normal activity in many ways, so once you start getting used to it, converting over the old Activities should be a breeze.
If you plan on using these tabs and you follow the Android design UI guidelines, you may want to use the TabHost in conjunction with a ViewPager. There is a great tutorial for this online that also allows for backward compatibility (down to at least 2.1) found here: http://thepseudocoder.wordpress.com/2011/10/13/android-tabs-viewpager-swipe-able-tabs-ftw/
Support library for fragments/viewpager: http://developer.android.com/tools/extras/support-library.html
More info about a TabHost and using Tabs with fragments can be found here:
http://developer.android.com/reference/android/widget/TabHost.html
http://thepseudocoder.wordpress.com/2011/10/04/android-tabs-the-fragment-way/
You can use TabLayout and a TabActivity to achieve layout in picture. Bad news is these are deprecated as of Android 3.0. Google advises to use fragments instead of these.
Is there way to inherit two different activities in android. I have to display the Map on my activity which inherit from some other activity. i want to display a map on that activity but i can't display the map without inheriting MapActivity. Is there any other way to display the map without using MapActivity.
No, android is java based. And java do not support multiple inheritance.
Java supports multiple interfaces.
Maybe using fragments will help. Fragments could simulate multiple activities. However, all "activities" must be available as fragment. I am not sure whether there exist one for maps
java does not support Multiple Inheritance, although you can come up with a clever design that will let you use functionality of multiple objects in your Activity.
read following article
http://csis.pace.edu/~bergin/patterns/multipleinheritance.html
I modified the pattern listed by Mayank to assume that one base Activity doesn't change. I also made some tweak to show how arguments would work, considering activities will need access to base activity. In the following link, assume map activity would be BaseActivityAlpha. Here is my posting: http://www.anotherandroidblog.com/2013/01/03/extending-from-two-activities
I have an Android app that I would like to convert to an Android library. The app is based around one activity whose entire XML layout contains only a webview that covers the entire screen. The library UI (really, just the webview) must now be integrated into the layout of other apps. For example, one parent app has a tab structure. I would like to have the library webview displayed in one of the tabs, with the tabs always visible at the bottom of the screen. Ordinarily, I'd opt to set the app-library boundary at the activity level but that does not work in this case -- we cannot pop up a new Activity from the library because that would cover all of the screen and the tabs at the bottom.
What is the best way to convert this to a library so that it works within the tab structure of the parent app? Where should the app-library boundary be? Some of my ideas are:
Let the library user create an activity with the custom layout that he prefers (tabs in this case). Make sure that the layout contains a webview. Use findViewById to get the webview object and pass this object into the library for the library to use to display pages. Main disadvantage here is that parts of the library need to hook up some Broadcast receivers onto the parent activity (which is not really part of the library in this scenario), and this coupling seems rather dubious.
Perhaps use fragments which were introduced in Android 3.0. However, these mostly seem geared towards tablets. Would these work in this case?
Is there another option compatible with Android 2.1+ that I am not aware of?
I decided to go with Fragments, using the compatibility library.
http://developer.android.com/guide/topics/fundamentals/fragments.html
http://developer.android.com/sdk/compatibility-library.html
Fragments are really the best choice in this case because:
They have a life cycle similar to that of activities, making conversion easy.
They are a chunk of UI with related functionality, which is exactly what's needed in this case.