Using android jetpack navigation in combination with toolbar and drawer is that the root destination has a hamburger menu icon (to toggle the drawer) and in child fragments there is a back button.
Also an animation exists when opening / closing child fragments on the back arrow.
Now the problem: In one of my child fragments I set a custom navigation back button
toolbar_main.setNavigationIcon(R.drawable.ic_clear)
This also works, but upon closing there is a "glitch" where
The custom icon disappears
The back arrow is visible for a short while (this is the "glitch"
The child closes and the root fragment (with burger icon) is visible again
Question:
Is this "glitch" a bug or do I have to call something other than setNavigationIcon (like ActionBarDrawerToggle or similar) ?
Solution: in each Fragment
override fun onAttach(context: Context) {
super.onAttach(context)
val activity = context as BaseActivity
if (navController.backStack.size > 3) {
activity.toolbar.setNavigationIcon(getNavigationIcon())
}
}
more than 3 because:
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/navigation"
app:startDestination="#+id/startFragment"> <----- always +1
<fragment
android:id="#+id/startFragment"> <----- startFragment + 1 = 2
<fragment
android:id="#+id/fragment_1"> <----- startFragment + 1 = 3
<fragment
android:id="#+id/fragment_2"> <----- startFragment + 1 = 3
</navigation>
Related
I am struggling in combining both up button to navigate back through my fragments and the overflow menu "hamburger" button that can open up the navigation drawer menu..
any suggestion how to make it work and have the menu icon on the right and the up button on the left like in the following picture
?
MainActivity.onCreate part:
setSupportActionBar(binding.toolbar)
.apply {
title = null
}
supportActionBar?.setHomeButtonEnabled(true)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
my Toolbar xml :
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/toolbar"
style="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/toolbarColor"
app:navigationIcon="#drawable/ic_baseline_menu_24" />
I tried adding
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController
val appBarConfiguration = AppBarConfiguration.Builder(R.id.foundLostFragment)
NavigationUI.setupActionBarWithNavController(
this,
navController,
appBarConfiguration.build()
)
but it just makes the up button act like the hamburger button so it opens the drawer menu and I cannot manage to have both of the icons displayed on the toolbar..
What I have done to fix my issue was creating a second menu for the toolbar itself with 1 menu item and overrided onOptionsItemSelected() to apply that when the toolbar item clicked I just open the drawer menu so in that way I have both up button and both menu item that opens my drawer layout menu :)
I have a video application - a video list and tapping on an item goes to video details. I want video details to be a full screen dialog fragment (to be able to do the motion layout animation from here https://medium.com/vrt-digital-studio/picture-in-picture-video-overlay-with-motionlayout-a9404663b9e7). But the previous dialog is not preserved behind (a blank screen is displayed). Weird enough BottomSheetDialogFragment works but DialogFragment does not.
So the question is - Should a dialog fragment have the previous fragment displayed under it when using jetpack navigation? Why bottom sheet works and dialog not?
Navigation is done using android jetpack navigation:
<action
android:id="#+id/action_videosFragment_to_video_details_nav_graph"
app:destination="#id/video_details_nav_graph"/>
and details nav graph:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/video_details_nav_graph"
app:startDestination="#id/videoDetailsFragment">
<dialog
android:id="#+id/videoDetailsFragment"
android:name="com.myapp.mobile.ui.video.VideoDetailsFragment"
android:label="VideoDetailsFragment"
tools:layout="#layout/fragment_video_details">
</dialog>
</navigation>
Am I missing something? Thanks
After looking more into it, managed to make it work with:
override fun onStart() {
super.onStart()
val dialog: Dialog? = dialog
if (dialog != null) {
val width = ViewGroup.LayoutParams.MATCH_PARENT
val height = ViewGroup.LayoutParams.MATCH_PARENT
dialog.window?.setLayout(width, height)
dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialog.window?.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
}
}
Please look at this video showing a shared elements activity transition.
It's a transition from a list activity to a detail activity.
[Video link no longer works]
As you can see the imageview gets drawn in front of the tabs.
What I would expect is the tabs being drawn in font on the imageview and fading out throughout the transition (so that at the end of the animation they are gone).
The only thing that seems to work is setting windowSharedElementsUseOverlay to true,
but that has other ugly effects, so that seems not to be an option.
The most commonly suggested approach is to include the tabs in the transition itself, but the problem is that the tabs are not there in the detail activity so they cannot be shared.
Code:
I start the detail activity like this:
options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, pairs);
ActivityCompat.startActivity(activity, subActivity, options.toBundle());
I believe what you may need is to exclude, rather than include, the tab layout from the transition animation.
So in the onCreate of your list activity, include:
Transition fade = new Fade();
fade.excludeTarget(R.id.tab, true); // use appropriate id for you tab
getWindow().setExitTransition(fade);
getWindow().setEnterTransition(fade); // try getWindow().setReenterTransition(fade); instead
Definitely have a look at Alex Lockwood's answer to How do I prevent the status bar and navigation bar from animating during an activity scene animation transition? where he gives a greater and more in-depth but digestible explanation on the topic. You may also want to consider adding/implementing the solution in that post.
You should try this:
On the exiting activity, call getWindow().setExitTransition(null);
On the entering activity, call getWindow().setEnterTransition(null);
It will prevent the fade out of the exiting activity and the fade in of the entering activity, which removes the apparent blinking effect and make transition smooth.
My calling activity has a both a tablayout and a toolbar within and each time I did the transition, the image would appear on top of both tablayout and toolbar, making the transition look untidy.
I fixed the problem quite elegantly by just adding a "dummy" tablayout and a "dummy" toolbar in my called activity. The "dummy" elements are not visible so it doesn't impact the layout of my called activity but the transition effect will work properly if you add them in.
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar2"
android:transitionName="toolbar"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
<android.support.design.widget.TabLayout
android:id="#+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="60dp"
android:visibility="gone"
android:transitionName="tab"
></android.support.design.widget.TabLayout>
I then added the tablayout and the toolbar as a pair in my transition:
Pair<View, String> p4 = Pair.create(getActivity().findViewById(R.id.sliding_tabs), "tab");
Pair<View, String> p5 = Pair.create(getActivity().findViewById(R.id.toolbar), "toolbar");
Bundle options = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(), p1, p2, p3, p4, p5).toBundle();
I am trying to learn Android development and have stumbled across the following thing I cannot solve.
I have imported Bottom Bar Navigation via Gradle to my app and have managed to set it up according to instructions. Here is what my screen looks like now.
As you can see, I have three tabs at the bottom that I am trying to use for navigation. The problem however is, that even though I know how to detect which element has been clicked via following:
mBottomBar.setItemsFromMenu(R.menu.bottombar_menu, new OnMenuTabClickListener() {
#Override
public void onMenuTabSelected(#IdRes int menuItemId) {
if (menuItemId == R.id.bb_menu_favorites) {
// The user selected item number one.
}
}
#Override
public void onMenuTabReSelected(#IdRes int menuItemId) {
if (menuItemId == R.id.bb_menu_favorites) {
// The user reselected item number one, scroll your content to top.
}
}
});
I have no idea how to actually perform the navigation request - e.g. when user moves to different tab, I want to show my other screen instead of Hello World! that you can see at the moment.
I believe that for this I need to actually change my activity_main.xml file as currently it looks like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
...
tools:context="com.example.robert.testproject.MainActivity">
<include layout="#layout/page_import"/>
</RelativeLayout>
This is where I have ended. As far as my understanding goes, I somehow need to use Intent (correct me if I am wrong) for the navigation purposes, but I am not quite sure how to handle this.
Any help in this matter - switching views, would be more than appreciated.
Use a Fragment for each bottom tab (3 Fragments for 3 views). Have a container layout(maybe a FrameLayout) in the Activity. Each Fragment will have different layouts. Replace the fragments based on what the user has tapped on the bottom bar.
I am creating an app with a WebView and an invisible menu on top of the page (it only appears when double clicked on the screen). That menu is a simple linear layout with buttons inside. Each button will start a different activity and I would like to make it so the menu would work in all activities.
I was thinking of creating a main layout that would consist of (invisible) menu on top and on the rest of the screen it would have the space for other activities. I want each activity to have its own layout aswell.
Maybe I could create that layout with menu on top and the rest of the space would be linear layout. Then I would call each activity inside that linear layout.
Is that possible and if it is, how to do it?
Any help will be appreciated.
as i understand you can do it like that :
1- create a class which extneds LinearLayout for the menu.
2- create a class extends activity and inside of it create that menu view
3- all your other activities should extends the activity you created in step 2.
4- inside all other activities onStart you should add menu view to the screen
but i strongly suggest you to use navigation Drawer.
http://developer.android.com/design/patterns/navigation-drawer.html and
http://developer.android.com/training/implementing-navigation/nav-drawer.html
You can achieve this by creating one Activity which have your invisible layout at top and a FrameLayout as container for your Fragments :
MainActivit.java
public class MainActivity(){
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main)
}
}
and activity_main.xml
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/invisible_menu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true" >
<!-- your other views here -->
</LinearLayout>
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/invisible_menu" />
</RelativeLayout>
That's the MainActivity which will hold all your Fragments. For using Fragments in your app you should check Android Developers - Fragments
Edit: Here is how you can add/replace Fragments via code:
To add your first Fragment simply call :
FragmentTransaction transaction = getFragmentManager().beginTransaction();
ExampleFragment fragment = new ExampleFragment();
transaction.add(R.id.fragment_container, fragment);
transaction.commit();
// Commit the transaction
transaction.commit();
And after that to replace the content with another Fragment , you should do something like this in your onClick :
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
So basically you should use FragmentTransaction.add() and FragmentTransaction.replace() .
If you want to support older versions of Android (i.e. avoiding fragments), you can use an <include> to add the menu layout to each activity. You'll need to hook up the click events in the onCreate of each activity, though you can encapsulate this code in another class.