For example, I have 2 activities which are named Main and Photos. I start Photos from Main. When I press back button when Photos activity opened, my navigation drawer menu is still selected. However, if I press back menu on action bar, Main activity refreshes, so selection disappears. I want to apply action bar back's event on back button. How can I do?
Its better to make your action bar button implement androids back buttons action rather than vice-versa, however, it can be done.
// Newer, but Im not sure what API version it came in
#Override
public void onBackPressed() {
//super.onBackPressed();
mMyAbBackBtn.callOnClick();
}
// Older, still supported
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (KeyEvent.KEYCODE_BACK == keyCode) {
mMyAbBackBtn.callOnClick();
return true; //handled
}
return super.onKeyUp(keyCode, event);
}
The "back button on action bar" is actually called an Up button. Just to clarify the differences: the Back button returns you to the previous activity (this could bring you to a different app) while the Up button will return you to the previous activity in the current application.
I'm quite confused how you have an Up button and a navigation drawer at the same time, would you put up some screenshots?
Assuming your "navigation drawer menu" isn't a native part of android that you're talking about, I don't recommend overriding your Back button to get your desired behavior.
Instead consider overriding onActivityCreated or onResume:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(); // don't restore the state
// alternatively:
// super.onActivityCreated(savedInstanceState); // you may have other things you
// want to preserve
// unSelect(); // your code to unselect whatever your navigation menu drawer is
}
#Override
public void onResume()
{
super.onResume();
unSelect(); // your code to unselect whatever your navigation menu drawer is
}
Related
Generally switching from one activity to another activity hamburger icon is replaced with back arrow. I want to control the functionality of that arrow. I have seen many contents here but most of them were related to hardware's back button. How can I control that?
I am trying the functionality in case of fragments. Also I have Navigation drawer attached with the hamburger icon.
I tried this-
if(id == android.R.id.home){
getSupportFragmentManager().beginTransaction().replace(R.id.main_container, new AmbulanceMap()).commit();
getSupportActionBar().setTitle("Book A Ride");
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
}
but doesnt work as I hoped.
I want my back button to change the fragmentto previous fragment.
I had the same problem once. Just like you, things like checking if Android.R.id.home is clicked didn't work.
But I solved it using that:
Set navigation listener to toolbar:
toolbar.setToolbarNavigationClickListener(v -> onBackPressed());
If it should be within fragment:
Create an public method in activity.
In fragment's onAttach (or later) cast getActivity() to your activity and call method you was defined previously.
Example:
// YourActivity
public void setHomeListener(OnLickListener listener){
toolbar.setToolbarNavigationClickListener(listener);
}
//Fragment's onCreate
((YourActivity)getActivity()).setHomeListener(v -> onBackPressed());
//Fragment's onDestroy
((YourActivity)getActivity()).setHomeListener(null);
And, of course, set home us up enabled to show back arrow.
EDIT
if you don't use labmdas u should use:
(YourActivity)getActivity()).setHomeListener(new OnClickListener() {
#Override
public void onClick(View v) {
YourFragment.this.onBackPressed();
}
});
The back button of the ActionBar is a menuItem so you need to override onOptionsItemSelected like this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
//Your back button logic here
break;
}
return true;
}
Also donĀ“t forget to add getSupportActionBar().setDisplayHomeAsUpEnabled(true); after setting the Toolbar
In my activity the action bar shows only the left arrow and the title of the activity.
When I press the left arrow the activity goes back to the previous activity, but no event is registered in the onKeyUp, OnkeyDown and OnBackPressed methods.
But when I press the Back key on the phone (at the bottom) the activity goes back to the previous one and all the methods onKeyUp, OnKeyDown and OnBackPressed register an event (in the logcat).
How can I capture that left arrow (I think it is called the UP button)?
The reason I need to capture the key is to know in the onPause method that the activity is destroyed by the user and not by the system (for example, if the user switches to another activity).
By further investigating he matter I found out that the UP button gives an event that is captured by the onOptionsItemSelected method and since there is no other button on the menu I know it is this button.
see http://developer.android.com/guide/topics/ui/actionbar.html#Handling
Handling clicks on action items
When the user presses an action, the system calls your activity's onOptionsItemSelected() method. Using the MenuItem passed to this method, you can identify the action by calling getItemId(). This returns the unique ID provided by the tag's id attribute so you can perform the appropriate action. For example:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case android.R.id.home:
onUpButtonPressed();
return true;
case R.id.action_search:
openSearch();
return true;
case R.id.action_compose:
composeMessage();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Note: If you inflate menu items from a fragment, via the Fragment
class's onCreateOptionsMenu() callback, the system calls
onOptionsItemSelected() for that fragment when the user selects one of
those items. However, the activity gets a chance to handle the event
first, so the system first calls onOptionsItemSelected() on the
activity, before calling the same callback for the fragment. To ensure
that any fragments in the activity also have a chance to handle the
callback, always pass the call to the superclass as the default
behavior instead of returning false when you do not handle the item.
To enable the app icon as an Up button, call setDisplayHomeAsUpEnabled(). For example:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
...
}
Yes you are right, you can detect if the up button was pressed in the onOptionsItemSelected method. This should work:
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// Do something here. This is the event fired when up button is pressed.
return true;
}
return super.onOptionsItemSelected(item);
}
I am creating an android application with three tabs using PageSlidingtabStrip as a library to create a swipe view.And it has three fragments.Each fragments has a list view.When the item of the listview is clicked it opens an activity and display the details.
The problem is how can i come back to the fragment in the main screen using back button in actionbar in the activity
And how can i go to the corresponding Fragment(Tab)
Try something like this :
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
Intent intent = new Intent(YourCurrentClass.this , ClassThatYouWantToGo.class);
startActivity(intent)
}
Or actually like #TommyTopas said, you can just Override onBackPressed and put this.finish();.
EDIT
As I've understood you want to use a button on your AcitonBar, then you have tod o something like this :
First set the HomeButton enabled doing :
getActionBar().setDisplayHomeAsUpEnabled(true); Then Override onOptionsItemSelected
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// or onBackPressed();
this.finish()
}
return true;
}
As I understand, when you return to the "Tab" Activity, you want to display the same tab in which the list item had been clicked. What you can do is, when a list item in any tab is clicked, save the tab number in onSavedInstanceState(), and when the Activity is recreated, then set the previously selected tab (if one was selected previously). You will get the savedInstanceState that you saved in onSavedInstanceState() back in the onCreate() of the same Activity.
You can provide an Up navigation by writing getActionBar().setDisplayHomeAsUpEnabled(true); and then in the onOptionsItemSelected method in the activity, if the item's id is android.R.id.home call the activity's method onBackPressed(); which will close your current activity and come back to your fragment
I've got a Main Activity which is a search interface, when the user clicks a result in the list, the result details are displayed in a Fragment. The Main Activity has an Action Bar, but in the details Fragment, the Action Bar is hidden. To hide the Action Bar in the Fragment, I'm calling a method in the Main Activity from the Fragment Activity like this: ((SearchInterface)getActivity()).hideABar();. Then when the user clicks the back button, they go back to the search interface and the Action Bar reappears. Doing that is a bit more complex than simply calling a method. I set up an Interface in the Main Activity and override the method in the Fragment like this:
Main Activity:
public interface Callback {
public void onBackPressedCallback();
}
#Override
public void onBackPressed() {
super.onBackPressed();
if(fragBackPressed != null)
fragBackPressed.onBackPressedCallback();
checkActionBarState();
}
...
public void checkActionBarState(){
bar_AB = getSupportActionBar();
boolean barVisible = bar_AB.isShowing();
if(barVisible){
Toast.makeText(getApplicationContext(),"ActionBar WAS Visible",Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(),"ActionBar WAS NOT Visible",Toast.LENGTH_LONG).show();
bar_AB.show();
}
}
Fragment:
#Override
public void onBackPressedCallback() {
Log.d("SSIVideoFrag", "checking action bar state");
}
So now, when the user presses the Back button while in the Details Fragment, they go back to Main Activity and the Action Bar reappears. Now I'd like to add a button in the Details Fragment that does what clicking the Back button does, but I can't figure out how to do it. I don't know how to override the onBackPressedCallback() method from within the onClick of a Button:
back_BTN.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
//--- what to do here?
}
});
simple:
getFragmentManager().popBackStack();
https://developer.android.com/reference/android/app/FragmentManager.html#popBackStack()
ps.: that's not an actual back press, your onBackPressed will not be called. But the fragment will be removed, just like in a back press.
I have a main activity that is situated with two navigation drawers. The left one is always accessible, but the right one is used for displaying some necessary lists and performing certain actions. When I have certain fragments loaded into the center FrameLayout of the activity they have actions that require the right drawer be opened and an item be selected. All of this is working great, but I want to make sure that when either the back button is pressed or the screen is clicked outside the drawer that the drawer is closed, locked and the fragment loaded in there is removed. I should also mention that this right drawer holds a FrameLayout and relies on fragments.
In my main activity this is what I'm calling:
#Override
public void onBackPressed(){
Log.d(TAG, "onBackPressed() called");
if(drawerLayoutRight.isDrawerOpen(drawerFrameRight)){
Log.d(TAG, "----------------------");
drawerLayoutRight.closeDrawer(drawerFrameRight);
drawerLayoutRight.setDrawerLockMode(1, drawerFrameRight);
ExcerciseList fragment = (ExcerciseList) getFragmentManager().findFragmentById(R.id.right_drawer);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.remove(fragment).commit();
} else {
super.onBackPressed();
}
}
I also tried:
public boolean onKeyDown(int keyCode, KeyEvent event){
if (keyCode == KeyEvent.KEYCODE_BACK) {
Log.d(TAG, "onKeyDown called");
return true;
}
return super.onKeyDown(keyCode, event);
}
But this hasn't worked either. Whenever I click the back button the drawer will close, but neither of these methods would be called. But once the drawer is closed, if the back button is pressed these methods will be invoked. I was also wondering if anyone knew of a simple way to handle a click outside of the drawer. I figure I could make a custom DrawerLayout and override drawerClose() or check the coordinates that are clicked on a touch event. Just curious if anyone has a simpler way.
Put this line into your code:
mDrawerLayout.setFocusableInTouchMode(false);
Then it will call your overwritten onBackPressed() when you press the back button.
Quoting myself from the question at Force EditText to lose focus when back pressed
"In my experience onBackPressed() (at least the default #Override one in an activity) will not normally fire when pushing the back button to close the keyboard. As far as I know it will only fire when a Back press would initiate a finish() on the current activity."
This probably applies the same way to the navigation drawer.
This is most likely due to the fact that the current "Activity" is not in focus when the drawer opens (same with the SoftKeyboard) so the #Override back button is not called.
I was able to solve my problem by using DrawerLayout.DrawerListener. This worked in my situation because when the back button was being pressed the drawer was still closing even though the method onBackPressed() wasn't being called.
#MH said, "The DrawerLayout (I assume that's what you're using) will consume the back button event if the drawer is opened."
Although in the documentation I could not find an explicit mention of this; there was some mention of the back button here. Unfortunately it was not of much help.
What #MH said explains why onBackPressed() was not being called when the drawer was opened, and why it was being called while it was closed.
drawerLayoutRight.setDrawerListener(this);
Where drawerLayoutRight is a DrawerLayout. And my listener looks like this:
#Override
public void onDrawerClosed(View arg0) {
if(drawerLayoutRight.getDrawerLockMode(drawerFrameRight)!= 1){
drawerLayoutRight.setDrawerLockMode(1, drawerFrameRight);
}
ExcerciseList fragment = (ExcerciseList) getFragmentManager().findFragmentById(R.id.right_drawer);
if (fragment != null) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.remove(fragment).commit();
}
}
onDrawerOpened(), onDrawerSlide() and onDrawerStateChanged() are all empty. Only one of my drawers is using the listener so I don't have to check the view.
Just simple overrede your activity or drawerlayout, will do.
#Override public boolean onKeyDown(int keyCode, KeyEvent event) {
if (KeyEvent.KEYCODE_BACK == keyCode
&& mDrawerLayout != null
&& mDrawerLayout.isDrawerOpen(leftDrawerView)) {
KeyEventCompat.startTracking(event);
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override public boolean onKeyUp(int keyCode, KeyEvent event) {
if (KeyEvent.KEYCODE_BACK == keyCode
&& !event.isCanceled()
&& mDrawerToggle != null
&& mDrawerLayout.isDrawerOpen(leftDrawerView)) {
mDrawerLayout.closeDrawers();
return true;
}
return super.onKeyUp(keyCode, event);
}
The problem, as #Alex Vasilkov indicated, seems to do something with the drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); method.
None of the suggestions above did work for me. So I wanted to write my own solution. I digged the source code of DrawerLayout Class and tried overriding onKeyDown and onKeyUp methods, but the Back Button click is not getting triggered at all, if the Lock mode is LOCK_MODE_LOCKED_CLOSED. I think this is a bug.
So in my case, I needed to lock left navigation drawer only, not the right one. And I ended up calling drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.START); this method to lock my left navigation drawer instead of calling drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); this method, which locks both of the drawers and causes this back button bug.
So as a summary, drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); disables back button click somehow. Maybe only if you have two navigation drawers.
After adding this line back button will manage to close DrawerLayout.
mDrawerLayout.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
I had a very similar issue with an empty list in a fragment (wouldn't respond to back button press when the list was empty) and some of the solutions mentioned here helped me solving my issue.
The fragment causing the issue with the "onBackPressed()":
<TextView
android:id="#android:id/empty"
... />
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
The issue is similar in that when the list returned by the adapter is empty (#android:id/empty), the first view (TextView) doesn't seem to be "considered" as a focusable/focused view by Android (whereas the second view - ListView - is).
So pressing the back button wouldn't be registered by the view currently displayed and wouldn't be caught by my custom code in the fragment (instead closing the activity directly).
In my case, adding the following to onCreateView solved my issue (and allowed the back button press to be caught by the fragment even when the list is empty):
View view = inflater.inflate(R.layout.fragment_content, container, false);
view.setFocusableInTouchMode(true);
view.requestFocus();
I know it is a bit late but still... this answer will help others
#Override
public void onBackPressed()
{
if (mDrawerLayout.isOpen())
mDrawerLayout.close();
else
super.onBackPressed();
}