In the activity class, I set up the actionbar as this:
MyActivity
setSupportActionBar(findViewById(R.id.toolbar_my))
supportActionBar?.apply {
setDisplayHomeAsUpEnabled(true)
setDisplayShowHomeEnabled(true)
}
Because I need to override onOptionsItemSelected(...) (in the fragment class), I didn't override onSupportNavigateUp() here.
This activity cotnains a fragment. What I want is, when click on the actionbar up button, besides pop back, also revoke a custom save() method.
So in the fragment's onOptionsItemSelected(...), write some code for the item.id == android.R.id.home case. However, I made a break point here, and found that when click on the up/home button, the code in the android.R.id.home case is never revoked. The other items' on selected methods work.
In the fragment class:
MyFragment
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) {
android.R.id.home -> {
// code here not gets called when click up/home button
mPresenter.save()
return true
}
R.id.edit-> {
// The code here is revoked when item selected.
}
else -> {
return super.onOptionsItemSelected(item)
}
}
}
I tried override another onOptionsItemSelected(...) method in the activity class, and write android.R.id.home case, still cannot invoke methods in it.
Why the code in item.id == android.R.id.home case is not called?
Read setHomeButtonEnabled
Enable or disable the "home" button in the corner of the action bar.
(Note that this is the application home/up affordance on the action
bar, not the systemwide home button.)
supportActionBar?.setHomeButtonEnabled(true)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
Then
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.getItemId()){
android.R.id.home -> {
mPresenter.save()
return true
}
R.id.edit-> {
// some code
}
}
return super.onOptionsItemSelected(item)
}
Related
I have a form and want to get a confirmation message from the user before the user leaves it.
i want provide custom back button when user touch this button:
i try this:
val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
}
}
requireActivity().onBackPressedDispatcher.addCallback(this,onBackPressedCallback)
but only seems to work for providing custom back behavior to the built-in software/hardware back button and not the back arrow button
How can I do this?
Use onSupportNavigateUp, and replace yourCurrentFragmentID to your current fragment id. All these should be done in MainActivity.
navController = findNavController(R.id.nav_host_fragment)
setupActionBarWithNavController(navController!!)
override fun onSupportNavigateUp(): Boolean {
return when(navController?.currentDestination?.id) {
R.id.yourCurrentFragmentID -> {
showDialog()
true
}
else -> navController?.navigateUp()!!
}
}
Edit
If your fragment already use onOptionsItemSelected, you can handle the logic by checking itemId.
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.itemId
if (id == R.id.save) {
// your save button code logic
}else if(id ==android.R.id.home){
// display confirmation message
}
return super.onOptionsItemSelected(item)
}
Use this code to set Activity on backpress.
override fun onBackPressed() {
if (isDiscardChanges) {
discardDialog()
} else {
super.onBackPressed()
}
}
If you only want to go back from Activity, then you can add within AndroidManifest.xml child class Activity.
android:parentActivityName="Parent_Activity_Name
I am creating a collapsing toolbar with navigationview it works so will but when I use onOptionsItemSelected to make a Toast when item of menu chooses, there is no Toast.
Could anyone help me to know What is wrong?
this is my MainActivity
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
main_nav_view.setNavigationItemSelectedListener(this)
//set navigation view
val toggle = ActionBarDrawerToggle(
this, main_drawer_layout, main_toolbar, R.string.navigation_drawer_open,
R.string.navigation_drawer_close
)
main_drawer_layout.addDrawerListener(toggle)
toggle.syncState()
}
override fun onNavigationItemSelected(menuItem: MenuItem): Boolean {
// set item as selected to persist highlight
menuItem.isChecked = true
closeDrawer()
return true
}
// close drawer when item is tapped
private fun closeDrawer() {
main_drawer_layout.closeDrawer(Gravity.START)
}
override fun onBackPressed() {
if (main_drawer_layout.isDrawerOpen(GravityCompat.START)) {
closeDrawer()
} else {
super.onBackPressed()
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// Handle presses on the action bar menu items
when (item.itemId) {
R.id.item1 -> {
Toast.makeText(this, "Item 1 pressed", Toast.LENGTH_LONG).show()
return true
}
}
return super.onOptionsItemSelected(item)
}
}
The context should be "MainActivity.this" instead of "this" since it's inside of a callback method.
What happens if you set a breakpoint on the Toast line? Is the breakpoint reached?
you must create a new function because it conflicts with the navigationselected. You can create a function called initNavigationDrawer () and call it in oncreate.
Try to set breakpoint in your line where you are expecting Toast. Maybe there is some problem with logic or id of element.
How to set breakpoint:
click near line number and red dot should appear
run in Debug mode
When program stops there it means that evertyhing is correct from logic point of view.
You can also try to change this in to this#MainActivity to pass proper contex (to method Toast.makeText(...)).
I'm currently running into a strange problem, similar to here Shared element transition when using ActionBar Back button but with a fragment to fragment shared element transition. It works fine when using the back button. As soon as the toolbar home is triggered it's just blinking. So calling finishAfterTransition() is no option here.
I call the same method both times. The base for back navigation
override fun onBackPressed() {
if (coordinator != null) {
coordinator!!.back()
} else {
finish()
}
}
and the intercepted toolbar home click.
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
return when (item?.itemId) {
android.R.id.home -> {
onBackPressed()
true
}
else -> return super.onOptionsItemSelected(item)
}
}
Update: Now I noted like one out of ten tries it works correctly.
I hope anyone of you guys has a clue why this happens.
Regards coffeelord
I have a menu inside the top actionbar that allows for changing a password, editing their profile, and logging out. What I need is, once they click the "edit bio" option, I want to add an arrow or a "<" to the actionbar on the left side to allow the user a "go back" option if they want to exit editing the profile as well as hiding the right side menu option while they are editing. Here's my code for inflating the menu on the right:
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
inflater!!.inflate(R.menu.profiletoolbar, menu)
super.onCreateOptionsMenu(menu, inflater)
}
//get the actionbar selction when pressed
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
R.id.userLogout -> {
FirebaseAuth.getInstance().signOut()
val i = Intent(context, Login::class.java)
startActivity(i)
true
}
R.id.editBio -> {
editProfileBio()
true
}
else -> super.onOptionsItemSelected(item)
}
I really want to understand what the process is behind how this works. Can someone help me? I'd also be okay with just replacing the menu on the right with an arrow or a "<" as well, although I don't like that idea as much.
How about this: setDisplayHomeAsUpEnabled()
R.id.editBio -> {
editProfileBio()
supportActionBar?.setDisplayHomeAsUpEnabled(true)
true
}
To handle when pressed:
override fun onBackPressed() {
super.onBackPressed()
// do your stuff when pressed the back Button
}
I'd also be okay with just replacing the menu on the right with an
arrow or a "<" as well, although I don't like that idea as much.
Don't like that idea either. By enabling back Button when editbio clicked, you'll have access to the current menu and there will be a back Button too so this seems to be the perfect way to do that.
You just have to listen for the R.id.home option
Add a toolbar to activity layout.
In your fragment declare that it needs to redraw the toolbar.
setHasOptionsMenu(true);
Set toolbar as action bar
private fun setActionBar() {
val toolbar = getActivity().findViewById(R.id.tb_main_toolbar)
if (toolbar != null) {
(getActivity() as AppCompatActivity).setSupportActionBar(toolbar)
}
val actionBar = (getActivity() as AppCompatActivity).supportActionBar
if (null != actionBar) {
customizeActionBar(actionBar)
}
}
private fun customizeActionBar(actionBar: ActionBar) {
actionBar.setDisplayHomeAsUpEnabled(true)
actionBar.setTitle(R.string.logout)
actionBar.setDisplayHomeAsUpEnabled(true)
actionbar.setDisplayShowHomeEnabled(true)
actionBar.setHomeAsUpIndicator(R.drawable.logout)
}
Override onOptionItemSelected and do your functionality
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home ->
FirebaseAuth.getInstance().signOut()
val i = Intent(context, Login::class.java)
startActivity(i)
true
}
return true
}
I'm developing an app with ActionBars which supports Gingerbread and up. So basically I'm using the support library and extending
ActionBarActivity
for all my activities. Everything works well except for the
onSupportNavigateUp()
method. It just does not get called as stated in the documentation.
This method is called whenever the user chooses to navigate Up within
your application's activity hierarchy from the action bar.
This is quite easy but I haven't been able to figure out why it does not work as expected nor Googling helped. Is this a bug? or am I missing something?
if you override onOptionsItemSelected, then onSupportNavigateUp will not be called.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// handle ⬅️ button here
break;
}
return true;
}
As said before, if you override OnOptionsItemSelected, OnSupportNavigateUp will not be called. you can make sure it gets called by adding a default: case inside the OnOptionsItemSelected like so:
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.something:
Intent intent = new Intent(this,someActivity.class);
startActivity(intent);
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
The super.onOptionsItemSelected(item) will make sure OnSupportNavigateUp is called. This is in case you don't want the case dealt inside your OnOptionsItemSelected
Have you set in your Manifest.xml file the parent activity? If yes, it won't be called. #see http://developer.android.com/reference/android/support/v7/app/ActionBarActivity.html#onSupportNavigateUp()
Who knew... onSupportNavigateUp() works only on 4.0 and above. For below onNavigateUp() is called.
It is also important to return true from onCreateOptionsMenu(), I have this set to false as I have custom menu but then onOptionsItemSelected() has not been called!
So use:
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
//menuInflater.inflate(R.menu.main, menu)
return true
}
And then
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
when (item.itemId) {
R.id.action_share -> return true
else -> return super.onOptionsItemSelected(item)
}
}
I had a same problem onSupportNavigateUp and onOptionsItemSelected was not calling
I need to prevent backPress on child fragments so I override setNavigationOnClickListener in toolbar
toolbar.setNavigationOnClickListener {
if(childFragmentHandleBackPressed()){
NavigationUI.navigateUp(
navController,
AppBarConfiguration(navController.graph, drawerLayout)
)
}
}
or you can use navController.navigateUp() if you don't want to open navigation drawer menu on start/root fragment
So actually when you override onOptionsItemSelected you should return false by default for the onSupportNavigateUp method to be called. See below
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_print -> {
doSomething()
return true
}
}
return false
}
override fun onSupportNavigateUp(): Boolean {
onBackPressed()
return true
}
You need to add this line in onCreate() method
supportActionBar?.setDisplayHomeAsUpEnabled(true)
along with on onSupportNavigateUp() method