How to intercept MainActivity's BottomNavigationView menu clicks from fragment
My app works like a Wizard. I have an Activity that serves as a centralization for all my fragments. There is a BottomNavigationView with a "Next" button that appears in each fragment to drive the wizard.
When I want to go next I call "action_next" from BottomNavMenu and it navigate to the next fragment.
But I need to perform some action's when the user presses the Next Button in the context of that fragment (like store the data inputted). Further, I need to cancel the navigation if there is any problem with data inputted by the user.
At first try i did this in my fragment:
val controller = NavHostFragment.findNavController(this)
controller.addOnNavigatedListener { controller, navDestination: NavDestination ->
when (navDestination.id) {
R.id.destination_setup_tournment -> {
proceedNavigation(controller, navDestination)
}
}
}
private fun proceedNavigation(controller: NavController, navDestination: NavDestination) {
val teams = teamAdapter.getItems()
if (validateSubmit(teams)){
presenter.saveTeams(teams)
}else{
//how to cancel navigation and stay on this fragment?
}
}
But it does not look good or even correct for me and I don't know how to cancel the navigation if something is wrong.
Here is the App's related files:
MainActivity:
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?colorPrimary"
android:theme="@style/ToolbarTheme" />
<fragment
android:id="@+id/nav_host_fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/navigation"
app:defaultNavHost="true" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:menu="@menu/bottom_nav"
style="@style/Widget.MaterialComponents.BottomNavigationView"
>
</com.google.android.material.bottomnavigation.BottomNavigationView>
bottom_nav.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/action_next" android:title="@string/tornment_mode" android:icon="@drawable/ic_navigate_next_black_24dp" />
</menu>
android kotlin bottomnavigationview android-jetpack android-navigation-component
add a comment |
My app works like a Wizard. I have an Activity that serves as a centralization for all my fragments. There is a BottomNavigationView with a "Next" button that appears in each fragment to drive the wizard.
When I want to go next I call "action_next" from BottomNavMenu and it navigate to the next fragment.
But I need to perform some action's when the user presses the Next Button in the context of that fragment (like store the data inputted). Further, I need to cancel the navigation if there is any problem with data inputted by the user.
At first try i did this in my fragment:
val controller = NavHostFragment.findNavController(this)
controller.addOnNavigatedListener { controller, navDestination: NavDestination ->
when (navDestination.id) {
R.id.destination_setup_tournment -> {
proceedNavigation(controller, navDestination)
}
}
}
private fun proceedNavigation(controller: NavController, navDestination: NavDestination) {
val teams = teamAdapter.getItems()
if (validateSubmit(teams)){
presenter.saveTeams(teams)
}else{
//how to cancel navigation and stay on this fragment?
}
}
But it does not look good or even correct for me and I don't know how to cancel the navigation if something is wrong.
Here is the App's related files:
MainActivity:
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?colorPrimary"
android:theme="@style/ToolbarTheme" />
<fragment
android:id="@+id/nav_host_fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/navigation"
app:defaultNavHost="true" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:menu="@menu/bottom_nav"
style="@style/Widget.MaterialComponents.BottomNavigationView"
>
</com.google.android.material.bottomnavigation.BottomNavigationView>
bottom_nav.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/action_next" android:title="@string/tornment_mode" android:icon="@drawable/ic_navigate_next_black_24dp" />
</menu>
android kotlin bottomnavigationview android-jetpack android-navigation-component
1
Why are you using a BottomNavigationView for a wizard like flow? BottomNavigationView is for global navigation between separate parts of your app.
– ianhanniballake
Nov 21 at 1:34
my intentation was to use something common to all fragments related to this activity, just changing the command executed by the button in the context of each fragment, but keeping the navigation flow.
– alexpfx
Nov 21 at 2:47
add a comment |
My app works like a Wizard. I have an Activity that serves as a centralization for all my fragments. There is a BottomNavigationView with a "Next" button that appears in each fragment to drive the wizard.
When I want to go next I call "action_next" from BottomNavMenu and it navigate to the next fragment.
But I need to perform some action's when the user presses the Next Button in the context of that fragment (like store the data inputted). Further, I need to cancel the navigation if there is any problem with data inputted by the user.
At first try i did this in my fragment:
val controller = NavHostFragment.findNavController(this)
controller.addOnNavigatedListener { controller, navDestination: NavDestination ->
when (navDestination.id) {
R.id.destination_setup_tournment -> {
proceedNavigation(controller, navDestination)
}
}
}
private fun proceedNavigation(controller: NavController, navDestination: NavDestination) {
val teams = teamAdapter.getItems()
if (validateSubmit(teams)){
presenter.saveTeams(teams)
}else{
//how to cancel navigation and stay on this fragment?
}
}
But it does not look good or even correct for me and I don't know how to cancel the navigation if something is wrong.
Here is the App's related files:
MainActivity:
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?colorPrimary"
android:theme="@style/ToolbarTheme" />
<fragment
android:id="@+id/nav_host_fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/navigation"
app:defaultNavHost="true" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:menu="@menu/bottom_nav"
style="@style/Widget.MaterialComponents.BottomNavigationView"
>
</com.google.android.material.bottomnavigation.BottomNavigationView>
bottom_nav.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/action_next" android:title="@string/tornment_mode" android:icon="@drawable/ic_navigate_next_black_24dp" />
</menu>
android kotlin bottomnavigationview android-jetpack android-navigation-component
My app works like a Wizard. I have an Activity that serves as a centralization for all my fragments. There is a BottomNavigationView with a "Next" button that appears in each fragment to drive the wizard.
When I want to go next I call "action_next" from BottomNavMenu and it navigate to the next fragment.
But I need to perform some action's when the user presses the Next Button in the context of that fragment (like store the data inputted). Further, I need to cancel the navigation if there is any problem with data inputted by the user.
At first try i did this in my fragment:
val controller = NavHostFragment.findNavController(this)
controller.addOnNavigatedListener { controller, navDestination: NavDestination ->
when (navDestination.id) {
R.id.destination_setup_tournment -> {
proceedNavigation(controller, navDestination)
}
}
}
private fun proceedNavigation(controller: NavController, navDestination: NavDestination) {
val teams = teamAdapter.getItems()
if (validateSubmit(teams)){
presenter.saveTeams(teams)
}else{
//how to cancel navigation and stay on this fragment?
}
}
But it does not look good or even correct for me and I don't know how to cancel the navigation if something is wrong.
Here is the App's related files:
MainActivity:
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?colorPrimary"
android:theme="@style/ToolbarTheme" />
<fragment
android:id="@+id/nav_host_fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/navigation"
app:defaultNavHost="true" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:menu="@menu/bottom_nav"
style="@style/Widget.MaterialComponents.BottomNavigationView"
>
</com.google.android.material.bottomnavigation.BottomNavigationView>
bottom_nav.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/action_next" android:title="@string/tornment_mode" android:icon="@drawable/ic_navigate_next_black_24dp" />
</menu>
android kotlin bottomnavigationview android-jetpack android-navigation-component
android kotlin bottomnavigationview android-jetpack android-navigation-component
asked Nov 21 at 0:35
alexpfx
1,68831841
1,68831841
1
Why are you using a BottomNavigationView for a wizard like flow? BottomNavigationView is for global navigation between separate parts of your app.
– ianhanniballake
Nov 21 at 1:34
my intentation was to use something common to all fragments related to this activity, just changing the command executed by the button in the context of each fragment, but keeping the navigation flow.
– alexpfx
Nov 21 at 2:47
add a comment |
1
Why are you using a BottomNavigationView for a wizard like flow? BottomNavigationView is for global navigation between separate parts of your app.
– ianhanniballake
Nov 21 at 1:34
my intentation was to use something common to all fragments related to this activity, just changing the command executed by the button in the context of each fragment, but keeping the navigation flow.
– alexpfx
Nov 21 at 2:47
1
1
Why are you using a BottomNavigationView for a wizard like flow? BottomNavigationView is for global navigation between separate parts of your app.
– ianhanniballake
Nov 21 at 1:34
Why are you using a BottomNavigationView for a wizard like flow? BottomNavigationView is for global navigation between separate parts of your app.
– ianhanniballake
Nov 21 at 1:34
my intentation was to use something common to all fragments related to this activity, just changing the command executed by the button in the context of each fragment, but keeping the navigation flow.
– alexpfx
Nov 21 at 2:47
my intentation was to use something common to all fragments related to this activity, just changing the command executed by the button in the context of each fragment, but keeping the navigation flow.
– alexpfx
Nov 21 at 2:47
add a comment |
1 Answer
1
active
oldest
votes
There's no way to 'cancel' a navigation event - you need to put your business logic on your button/listener itself and only call navigate()
when you actually want to navigate.
The Creating event callbacks to the activity documentation goes over one approach for connecting your Activity and Fragment together by using onAttach(Context)
to get a reference to your Activity and set a property, callback, etc.
For example, you might consider doing something like:
// In your Activity
var onNextClicked: () -> Unit = {}
// In your Activity's onCreate()
button.setOnClickListener = View.OnClickListener {
onNextClicked.invoke()
}
// In your Fragment
override fun onAttach(context: Context) {
(context as YourActivity).onNextClicked = {
val teams = teamAdapter.getItems()
if (validateSubmit(teams)){
presenter.saveTeams(teams)
findNavController().navigate(R.id.action_next)
}
}
}
Each Fragment would set what they want the next button to do, allowing you full control over what the button does.
If you're dead set on the BottomNavigationView instead of just using an actual Button, you'd want to set your own OnNavigationItemSelectedListener
and have that listener call the onNextClicked
lambda if you're using this example.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53403692%2fhow-to-intercept-mainactivitys-bottomnavigationview-menu-clicks-from-fragment%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
There's no way to 'cancel' a navigation event - you need to put your business logic on your button/listener itself and only call navigate()
when you actually want to navigate.
The Creating event callbacks to the activity documentation goes over one approach for connecting your Activity and Fragment together by using onAttach(Context)
to get a reference to your Activity and set a property, callback, etc.
For example, you might consider doing something like:
// In your Activity
var onNextClicked: () -> Unit = {}
// In your Activity's onCreate()
button.setOnClickListener = View.OnClickListener {
onNextClicked.invoke()
}
// In your Fragment
override fun onAttach(context: Context) {
(context as YourActivity).onNextClicked = {
val teams = teamAdapter.getItems()
if (validateSubmit(teams)){
presenter.saveTeams(teams)
findNavController().navigate(R.id.action_next)
}
}
}
Each Fragment would set what they want the next button to do, allowing you full control over what the button does.
If you're dead set on the BottomNavigationView instead of just using an actual Button, you'd want to set your own OnNavigationItemSelectedListener
and have that listener call the onNextClicked
lambda if you're using this example.
add a comment |
There's no way to 'cancel' a navigation event - you need to put your business logic on your button/listener itself and only call navigate()
when you actually want to navigate.
The Creating event callbacks to the activity documentation goes over one approach for connecting your Activity and Fragment together by using onAttach(Context)
to get a reference to your Activity and set a property, callback, etc.
For example, you might consider doing something like:
// In your Activity
var onNextClicked: () -> Unit = {}
// In your Activity's onCreate()
button.setOnClickListener = View.OnClickListener {
onNextClicked.invoke()
}
// In your Fragment
override fun onAttach(context: Context) {
(context as YourActivity).onNextClicked = {
val teams = teamAdapter.getItems()
if (validateSubmit(teams)){
presenter.saveTeams(teams)
findNavController().navigate(R.id.action_next)
}
}
}
Each Fragment would set what they want the next button to do, allowing you full control over what the button does.
If you're dead set on the BottomNavigationView instead of just using an actual Button, you'd want to set your own OnNavigationItemSelectedListener
and have that listener call the onNextClicked
lambda if you're using this example.
add a comment |
There's no way to 'cancel' a navigation event - you need to put your business logic on your button/listener itself and only call navigate()
when you actually want to navigate.
The Creating event callbacks to the activity documentation goes over one approach for connecting your Activity and Fragment together by using onAttach(Context)
to get a reference to your Activity and set a property, callback, etc.
For example, you might consider doing something like:
// In your Activity
var onNextClicked: () -> Unit = {}
// In your Activity's onCreate()
button.setOnClickListener = View.OnClickListener {
onNextClicked.invoke()
}
// In your Fragment
override fun onAttach(context: Context) {
(context as YourActivity).onNextClicked = {
val teams = teamAdapter.getItems()
if (validateSubmit(teams)){
presenter.saveTeams(teams)
findNavController().navigate(R.id.action_next)
}
}
}
Each Fragment would set what they want the next button to do, allowing you full control over what the button does.
If you're dead set on the BottomNavigationView instead of just using an actual Button, you'd want to set your own OnNavigationItemSelectedListener
and have that listener call the onNextClicked
lambda if you're using this example.
There's no way to 'cancel' a navigation event - you need to put your business logic on your button/listener itself and only call navigate()
when you actually want to navigate.
The Creating event callbacks to the activity documentation goes over one approach for connecting your Activity and Fragment together by using onAttach(Context)
to get a reference to your Activity and set a property, callback, etc.
For example, you might consider doing something like:
// In your Activity
var onNextClicked: () -> Unit = {}
// In your Activity's onCreate()
button.setOnClickListener = View.OnClickListener {
onNextClicked.invoke()
}
// In your Fragment
override fun onAttach(context: Context) {
(context as YourActivity).onNextClicked = {
val teams = teamAdapter.getItems()
if (validateSubmit(teams)){
presenter.saveTeams(teams)
findNavController().navigate(R.id.action_next)
}
}
}
Each Fragment would set what they want the next button to do, allowing you full control over what the button does.
If you're dead set on the BottomNavigationView instead of just using an actual Button, you'd want to set your own OnNavigationItemSelectedListener
and have that listener call the onNextClicked
lambda if you're using this example.
answered Nov 21 at 4:06
ianhanniballake
102k14214226
102k14214226
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53403692%2fhow-to-intercept-mainactivitys-bottomnavigationview-menu-clicks-from-fragment%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Why are you using a BottomNavigationView for a wizard like flow? BottomNavigationView is for global navigation between separate parts of your app.
– ianhanniballake
Nov 21 at 1:34
my intentation was to use something common to all fragments related to this activity, just changing the command executed by the button in the context of each fragment, but keeping the navigation flow.
– alexpfx
Nov 21 at 2:47