Manage toolbar's navigation and back button from fragment in android - android

All of my fragments are controlled through ActionBarActivity (mainActivity), inside mainActivity a DrawerLayout is implemented and all the child fragments are pushed through drawerLayout's list item click. The problem that I'm facing is after pushing a fragment through drawerLayout I want to change the drawer icon into back icon of ToolBar so that user can navigate to previous fragment and to handle the callback of android.R.id.home either inside the same fragment or inside the mainActivity.
The code that I am using is:
MainActivity.java
public class MainActivity extends ActionBarActivity {
private DrawerLayout layoutDrawer;
private ActionBarDrawerToggle drawerToggler;
private Stack<Fragment> stack;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
stack = new Stack<Fragment>();
layoutDrawer = (DrawerLayout) findViewById(R.id.layout_drawer);
drawerToggler = new ActionBarDrawerToggle(this, layoutDrawer, toolbar,
R.string.app_name, R.string.app_name);
layoutDrawer.setDrawerListener(drawerToggler);
setUpDrawerList();
pushFragment(new FirstFragment(), true);
Session.setContext(getApplicationContext());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (drawerToggler.isDrawerIndicatorEnabled()
&& drawerToggler.onOptionsItemSelected(item))
return true;
switch (item.getItemId()) {
case android.R.id.home:
Toast.makeText(this, "Back from activity", Toast.LENGTH_SHORT)
.show();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
drawerToggler.syncState();
}
#Override
public void onBackPressed() {
popFragment();
}
private void setUpDrawerList() {
ListView listView = (ListView) findViewById(R.id.list_drawer);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
Arrays.asList(new String[] { "First Fragment",
"Second Fragment" }));
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
layoutDrawer.closeDrawers();
drawerToggler.setDrawerIndicatorEnabled(false);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
pushFragment(getFragment(position), true);
}
});
}
private Fragment getFragment(int pos) {
switch (pos) {
case 0:
return new FirstFragment();
case 1:
return new SecondFragment();
}
return null;
}
public void pushFragment(Fragment fragment, boolean add) {
FragmentTransaction transation = getSupportFragmentManager()
.beginTransaction();
if (add)
stack.push(fragment);
transation.replace(R.id.layout_content, fragment);
transation.commit();
}
public void popFragment() {
if (!stack.isEmpty()) {
Fragment fragment = stack.elementAt(stack.size() - 2);
stack.pop();
pushFragment(fragment, false);
} else
super.onBackPressed();
drawerToggler.setDrawerIndicatorEnabled(stack.size() == 1);
}
public void clearBackStack() {
stack.clear();
}
}
FirstFragment.java
public class FirstFragment extends Fragment {
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_first, container, false);
}
#Override
public void onResume() {
super.onResume();
ActionBar actionBar = ((ActionBarActivity)getActivity()).getSupportActionBar();
actionBar.setTitle("First Fragment");
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
inflater.inflate(R.menu.fragment_menu, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case android.R.id.home:
Toast.makeText(getActivity(), "Back from fragment", Toast.LENGTH_SHORT).show();
getActivity().onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
}
From the above code I am not able to get the callback of android.R.id.home and setting home button is not working everytime actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeButtonEnabled(true);
Any help will be really appreciated.
Thanks

Add a toolbar to your xml
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fragment title"/>
</android.support.v7.widget.Toolbar>
Then inside your onCreateView method in the Fragment:
Toolbar toolbar = view.findViewById(R.id.toolbar);
toolbar.setNavigationIcon(R.drawable.ic_back_button);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getActivity().onBackPressed();
}
});

You have to manage your back button pressed action on your main Activity because your main Activity is container for your fragment.
First, add your all fragment to transaction.addToBackStack(null) and now navigation back button call will be going on main activity. I hope following code will help you...
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
}
return super.onOptionsItemSelected(item);
}
you can also use
Fragment fragment =fragmentManager.findFragmentByTag(Constant.TAG);
if(fragment!=null) {
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.remove(fragment).commit();
}
And to change the title according to fragment name from fragment you can use the following code:
activity.getSupportActionBar().setTitle("Keyword Report Detail");

I have head around lots of solutions and none of them works perfectly. I've used variation of solutions available in my project which is here as below. Please use this code inside class where you are initialising toolbar and drawer layout.
getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
#Override
public void onBackStackChanged() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
drawerFragment.mDrawerToggle.setDrawerIndicatorEnabled(false);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);// show back button
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});
} else {
//show hamburger
drawerFragment.mDrawerToggle.setDrawerIndicatorEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
drawerFragment.mDrawerToggle.syncState();
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
drawerFragment.mDrawerLayout.openDrawer(GravityCompat.START);
}
});
}
}
});

Probably the cleanest solution:
abstract class NavigationChildFragment : Fragment() {
abstract fun onCreateChildView(inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View?
override fun onCreateView(inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val activity = activity as? MainActivity
activity?.supportActionBar?.setDisplayHomeAsUpEnabled(true)
setHasOptionsMenu(true)
return onCreateChildView(inflater, container, savedInstanceState)
}
override fun onDestroyView() {
val activity = activity as? MainActivity
activity?.supportActionBar?.setDisplayHomeAsUpEnabled(false)
setHasOptionsMenu(false)
super.onDestroyView()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val activity = activity as? MainActivity
return when (item.itemId) {
android.R.id.home -> {
activity?.onBackPressed()
true
}
else -> super.onOptionsItemSelected(item)
}
}
}
Just use this class as parent for all Fragments that should support navigation.

You can use Toolbar inside the fragment and it is easy to handle. First add Toolbar to layout of the fragment
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:minHeight="?attr/actionBarSize"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:background="?attr/colorPrimaryDark">
</android.support.v7.widget.Toolbar>
Inside the onCreateView Method in the fragment you can handle the toolbar like this.
Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
toolbar.setTitle("Title");
toolbar.setNavigationIcon(R.drawable.ic_arrow_back);
IT will set the toolbar,title and the back arrow navigation to toolbar.You can set any icon to setNavigationIcon method.
If you need to trigger any event when click toolbar navigation icon you can use this.
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//handle any click event
});
If your activity have navigation drawer you may need to open that when click the navigation back button. you can open that drawer like this.
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DrawerLayout drawer = (DrawerLayout) getActivity().findViewById(R.id.drawer_layout);
drawer.openDrawer(Gravity.START);
}
});
Full code is here
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//inflate the layout to the fragement
view = inflater.inflate(R.layout.layout_user,container,false);
//initialize the toolbar
Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
toolbar.setTitle("Title");
toolbar.setNavigationIcon(R.drawable.ic_arrow_back);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//open navigation drawer when click navigation back button
DrawerLayout drawer = (DrawerLayout) getActivity().findViewById(R.id.drawer_layout);
drawer.openDrawer(Gravity.START);
}
});
return view;
}

First you add the Navigation back button
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
Then, add the Method in your HostActivity.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId()==android.R.id.home)
{
super.onBackPressed();
Toast.makeText(this, "OnBAckPressed Works", Toast.LENGTH_SHORT).show();
}
return super.onOptionsItemSelected(item);
}
Try this, definitely work.

if you are using androidx fragment and want to go back to MainActivity when back home button is clicked, use the following codes .
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true);
....
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
requireActivity().onBackPressed();
}
return super.onOptionsItemSelected(item);
}

(Kotlin)
In the activity hosting the fragment(s):
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
onBackPressed()
return true
}
}
return super.onOptionsItemSelected(item)
}
I have found that when I add fragments to a project, they show the action bar home button by default, to remove/disable it put this in onViewCreated() (use true to enable it if it is not showing):
val actionBar = this.requireActivity().actionBar
actionBar?.setDisplayHomeAsUpEnabled(false)

The easiest solution I found was to simply put that in your fragment :
androidx.appcompat.widget.Toolbar toolbar = getActivity().findViewById(R.id.toolbar);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
NavController navController = Navigation.findNavController(getActivity(),
R.id.nav_host_fragment);
navController.navigate(R.id.action_position_to_destination);
}
});
Personnaly I wanted to go to another page but of course you can replace the 2 lines in the onClick method by the action you want to perform.

Generic method in Kotlin which can handle both the title bar back press action as well as navigation bar back press action and can be called from all the fragments is :
fun configureToolbarBackPress(
customToolBar: Toolbar,
parentVw: View,
activity: Activity,
title: String,
targetResId: Int
) {
customToolBar.setNavigationIcon(R.drawable.ic_arrow_back)
customToolBar.title = title
customToolBar.setNavigationOnClickListener {
parentVw.findNavController().navigate(targetResId)
}
(activity as DashboardActivityNew).onBackPressedDispatcher.addCallback(
object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
parentVw.findNavController().navigate(targetResId)
}
}
)
}
Now call this method onViewCreated() from any of the fragment as follows :
AppUtils.configureToolbarBackPress(
customToolbar as Toolbar,
view,
requireActivity(),
getString(R.string.title),
R.id.mainFragment
)
Include the toolbar in fragment.xml as follows :
<include
android:id="#+id/customToolbar"
layout="#layout/dashboard_toolbar" />
The layout of dashboard_toolbar.xml is as follows :
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="#dimen/abc_action_bar_default_height_material"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:background="#color/colorPrimary"/>

OnToolBar there is a navigation icon at left side
Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
toolbar.setTitle(getResources().getString(R.string.title_activity_select_event));
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
By using this at left side navigation icon appear and on navigation icon click it call parent activity.
and in manifest we can notify system about parent activity.
<activity
android:name=".CategoryCloudSelectActivity"
android:parentActivityName=".EventSelectionActivity"
android:screenOrientation="portrait" />

Related

Add back button to Toolbar for all Fragments other than Home Fragment which opens Navigation Drawer

When my application is opened Home screen is shown first.On Home screen I have NavigationDrawer which get opened after pressing HamburgerIcon.Later i go to different fragments.When I am in Other fragments other than Home Activity I need to show back button on Toolbar to come to previous fragment.But its every time showing Hamburger icon.How to do this ?
This is code for setting Toolbar in XML
<android.support.v4.widget.DrawerLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/drawerLayout"
tools:context="biz.fyra.myApp.ActivityTwo">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ccc"
android:minHeight="?attr/actionBarSize">
<ImageView
android:id="#+id/tooImage"
android:src="#drawable/latest"
android:layout_width="match_parent"
android:layout_gravity="center_horizontal"
android:layout_height="40dp" />
</android.support.v7.widget.Toolbar>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/frame">
</FrameLayout>
</LinearLayout>
<android.support.design.widget.NavigationView
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/nav_header"
android:id="#+id/navigationView"
app:menu="#menu/actionmenu"
android:background="#android:color/white">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
How to achieve this ?
If i understand right, you are using one activity with fragments replacing. So, looking at that you would have something like this:
Important: Activity theme should extends Theme.AppCompat.Light.NoActionBar
Activity:
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private DrawerLayout drawer;
private Toolbar toolbar;
private ActionBarDrawerToggle toggle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
drawer = findViewById(R.id.drawer);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toggle = new ActionBarDrawerToggle(
this,
drawer,
toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close
);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
// First creation
if (savedInstanceState == null)
showFragment(StartFragment.newInstance());
}
/**
* Using in Base Fragment
*/
protected ActionBarDrawerToggle getToggle() {
return toggle;
}
#Override
public void onBackPressed() {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.frame);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else if (fragment instanceof OnBackPressedListener) {
((OnBackPressedListener) fragment).onBackPressed();
} else {
super.onBackPressed();
}
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
drawer.closeDrawer(GravityCompat.START);
switch (item.getItemId()) {
case R.id.start: {
showFragment(StartFragment.newInstance());
break;
}
case R.id.orders: {
showFragment(OrdersFragment.newInstance());
break;
}
case R.id.category: {
showFragment(CategoryFragment.newInstance());
break;
}
case R.id.calendar: {
showFragment(CalendarFragment.newInstance());
break;
}
case R.id.settings: {
showFragment(SettingsFragment.newInstance());
break;
}
case R.id.about: {
showFragment(AboutFragment.newInstance());
break;
}
return true;
}
private void showFragment(Fragment fragment) {
getSupportFragmentManager().beginTransaction().replace(R.id.frame, fragment).commit();
}
}
Interface for sending backpress events from activity to fragments:
public interface OnBackPressedListener {
void onBackPressed();
}
And Abstract Base Fragment which you should extends and implement methods:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import ...
/**
* Abstract fragment with FAB button, Toolbar and 2 interfaces:
OnClick, OnBackPress
*
*/
public abstract class BaseFragment extends Fragment implements
View.OnClickListener, OnBackPressedListener {
protected FloatingActionButton fab;
protected Toolbar toolbar;
protected ActionBar actionBar;
protected ActionBarDrawerToggle toggle;
protected DrawerLayout drawer;
protected boolean mToolBarNavigationListenerIsRegistered = false;
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
fab = ((MainActivity)getActivity()).findViewById(R.id.fab);
toolbar = ((MainActivity) getActivity()).findViewById(R.id.toolbar);
actionBar = ((MainActivity) getActivity()).getSupportActionBar();
drawer = ((MainActivity) getActivity()).findViewById(R.id.drawer_layout);
toggle = ((MainActivity) getActivity()).getToggle();
fab.setOnClickListener(this);
}
/**
* Simplify fragment replacing in child fragments
*/
protected void replaceFragment(#NonNull Fragment fragment) {
FragmentManager fm = getActivity().getSupportFragmentManager();
fm.beginTransaction().replace(R.id.container, fragment).commit();
}
// hide FAB button
protected void hideFab() {
fab.hide();
}
//show FAB button
protected void showFab() {
fab.show();
}
/**
* Shows Home button as Back button
* Took from here {#link}https://stackoverflow.com/a/36677279/9381524
* <p>
* To keep states of ActionBar and ActionBarDrawerToggle synchronized,
* when you enable on one, you disable on the other.
* And as you may notice, the order for this operation is disable first, then enable - VERY VERY IMPORTANT!!!
*
* #param show = true to show <showHomeAsUp> or show = false to show <Hamburger> button
*/
protected void showBackButton(boolean show) {
if (show) {
// Remove hamburger
toggle.setDrawerIndicatorEnabled(false);
// Show back button
actionBar.setDisplayHomeAsUpEnabled(true);
// when DrawerToggle is disabled i.e. setDrawerIndicatorEnabled(false), navigation icon
// clicks are disabled i.e. the UP button will not work.
// We need to add a listener, as in below, so DrawerToggle will forward
// click events to this listener.
if (!mToolBarNavigationListenerIsRegistered) {
toggle.setToolbarNavigationClickListener(v -> onBackPressed());
mToolBarNavigationListenerIsRegistered = true;
}
} else {
// Remove back button
actionBar.setDisplayHomeAsUpEnabled(false);
// Show hamburger
toggle.setDrawerIndicatorEnabled(true);
// Remove the/any drawer toggle listener
toggle.setToolbarNavigationClickListener(null);
mToolBarNavigationListenerIsRegistered = false;
}
// So, one may think "Hmm why not simplify to:
// .....
// getSupportActionBar().setDisplayHomeAsUpEnabled(enable);
// mDrawer.setDrawerIndicatorEnabled(!enable);
// ......
// To re-iterate, the order in which you enable and disable views IS important #dontSimplify.
}
/**
* Simplify setTitle in child fragments
*/
protected void setTitle(int resId) {
getActivity().setTitle(getResources().getString(resId));
}
//
#Override
public abstract void onClick(View v);
// Handles BackPress events from MainActivity
#Override
public abstract void onBackPressed();
}
All fragments with Back Button used in MainActivity should extends from this BaseFragment.
You can try something like
#Override
protected void onCreate(Bundle savedInstanceState)
{ super.onCreate(savedInstanceState);
[...]
if (getSupportActionBar() != null)
{ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
}
[...]
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{ if (getSupportFragmentManager().getBackStackEntryCount() > 0)
{ switch (item.getItemId())
{ case android.R.id.home:
onBackPressed();
return true;
}
}
[...]
}

How to handle back arrow click?

I am developing an Android app about music. In this app, I have two fragments: PopFragment e GenresFragment.
In the XML file of PopFragment called fragment_pop.xml, I have toolbar with a back arrow that goes back to GenresFragment.
My toolbar code is this:
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
>
<include
android:layout_height="wrap_content"
android:layout_width="match_parent"
layout="#layout/toolbar_layout"
/>
</android.support.design.widget.AppBarLayout>
<ImageButton
android:id="#+id/arrowPop"
android:layout_width="54dp"
android:layout_height="wrap_content"
android:src="#drawable/ic_arrow_back_black_24dp"
style="?android:attr/borderlessButtonStyle"
/>
In the Java file of PopFragment called PopActivity, I have some code but it's not working.
I have this code:
public class PopActivity extends AppCompatActivity implements View.OnClickListener {
public PopActivity() {
// Required empty public constructor
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_pop);
Toolbar toolbar = (Toolbar)findViewById(R.id.toolBar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
ImageButton backBtn = (ImageButton)findViewById(R.id.arrowPop);
}
#Override
public void onClick (View view) {
Intent i = new Intent();
switch (view.getId()) {
case R.id.arrowPop:
break;
}
}
Can you help me please?
Thank you
Try something like:
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
inflater.inflate(R.menu.your_menu, menu);
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home: {
getActivity().onBackPressed();
break;
}
}
return true;
}
You generally don't need to add your own arrow icon, the Toolbar should be able to handle it for you.
if(shouldShowArrow()) {
drawerLayout.setDrawerLockMode(LOCK_MODE_LOCKED_CLOSED, GravityCompat.START);
drawerToggle.setDrawerIndicatorEnabled(false);
MyActivity.this.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} else { // hamburglar icon
drawerLayout.setDrawerLockMode(LOCK_MODE_UNLOCKED, GravityCompat.START);
MyActivity.this.getSupportActionBar().setDisplayHomeAsUpEnabled(false);
drawerToggle.setDrawerIndicatorEnabled(true);
}
drawerToggle.syncState();
And then you can define what happens when you click the arrow
#Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
drawerToggle = new ActionBarDrawerToggle(MyActivity.this, drawerLayout, toolbar, R.string.open, R.string.close) {
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
MyActivity.this.supportInvalidateOptionsMenu();
}
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
MyActivity.this.supportInvalidateOptionsMenu();
}
};
drawerLayout.setDrawerListener(drawerToggle);
drawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// what to do when you click the arrow
}
});
actionBar.setDisplayHomeAsUpEnabled(false);
actionBar.setHomeButtonEnabled(true);
}
#Override
protected void onPostCreate(Bundle bundle) {
super.onPostCreate(bundle);
drawerToggle.syncState();
}
#Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
drawerToggle.onConfigurationChanged(newConfig);
}
Use the following code as a quick fix, which mimics the back button being pressed.
switch (view.getId()) {
case R.id.arrowPop:
onBackPressed();
break;
}
Using this code, you shouldn't have to define the back button in the toolbar yourself, Android will handle it.
Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
Then when you click the back button, Android will call onBackPressed() for you.

Up Navigation (Action Bar's back arrow) is not working for fragments

I've drawer-layout as a base layout of my activity and I'm replacing two fragments on a frame present inside this drawer-layout. The first fragment is not added in fragment's back stack. I'm displaying hamburger icon in my activity (I also want the drawer menu in my first fragment). In second fragment I disabled the hamburger icon by mActionBarDrawerToggle.setDrawerIndicatorEnabled(false) and enabled back button using actionBar.setDisplayHomeAsUpEnabled(true).
In first fragments onResume I enabled hamburger icon by mActionBarDrawerToggle.setDrawerIndicatorEnabled(true)` so that when user presses back button (both hardware and action-bar's up button) from second fragment,user will come back to first fragment and hamburger icon will be enabled. Everything is working fine only I'm not able to go back from second fragments action bar back button. I'm not able to click it.
Below is my code :-
Activity code
if (Utility.isLargeScreen(this))
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
else
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
mHiddenGemsApplication = (HiddenGemsApplication) getApplication();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
initViews();
setSupportActionBar(mToolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayHomeAsUpEnabled(true);
}
mTextViewActionBarTitle.setText(getString(R.string.app_name));
mActionBarDrawerToggle = new ActionBarDrawerToggle(HomeActivity.this, mDrawerLayout, mToolbar, R.string.open_drawer, R.string.close_drawer) {
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
}
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
};
mDrawerLayout.setDrawerListener(mActionBarDrawerToggle);
mActionBarDrawerToggle.syncState();
mFragmentManager = getSupportFragmentManager();
replaceFragment(new CategoryFragment(), getString(R.string.app_name), CategoryFragment.TAG);
#Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
mDrawerLayout.closeDrawers();
return;
}
super.onBackPressed();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
if (mFragmentManager.getBackStackEntryCount() > 0) {
mFragmentManager.popBackStack();
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void replaceFragment(Fragment fragment, String actionBarTitle, String tag) {
if (mFragmentManager == null)
return;
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment, tag);
if (!tag.equals(CategoryFragment.TAG))
fragmentTransaction.addToBackStack(tag);
fragmentTransaction.commit();
setActionBarTitle(actionBarTitle);
}
public void setActionBarTitle(String actionBarTitle) {
if (!TextUtils.isEmpty(actionBarTitle))
mTextViewActionBarTitle.setText(actionBarTitle);
}
public void setDrawerIndicatorEnabled(boolean value) {
if (mActionBarDrawerToggle != null) {
mActionBarDrawerToggle.setDrawerIndicatorEnabled(value);
}
}
Activity XML
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="nirvaniclabs.com.hiddengems.activities.HomeActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include
android:id="#+id/toolbarlayout"
layout="#layout/toolbar_layout" />
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/toolbarlayout" />
</RelativeLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="#menu/navigation_items" />
</android.support.v4.widget.DrawerLayout>
First Fragment : -
private Button mButtonTemp;
private AppCompatActivity mActivity;
public static String TAG = "CategoryFragment";
public CategoryFragment() {
// Required empty public constructor
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof Activity)
mActivity = (AppCompatActivity) context;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View viewGroup = inflater.inflate(R.layout.fragment_category, container, false);
initViews(viewGroup);
mButtonTemp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((HomeActivity) mActivity).replaceFragment(new TripListFragment(), "Trip Fragment", TripListFragment.TAG);
}
});
return viewGroup;
}
private void initViews(View viewGroup) {
mButtonTemp = (Button) viewGroup.findViewById(R.id.btn_temp);
}
#Override
public void onResume() {
super.onResume();
((HomeActivity) mActivity).setDrawerIndicatorEnabled(true);
((HomeActivity) mActivity).setActionBarTitle(getString(R.string.app_name));
}
Second Fragment
private AppCompatActivity mActivity;
public static String TAG = "TripListFragment";
public TripListFragment() {
// Required empty public constructor
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof Activity)
mActivity = (AppCompatActivity) context;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
ActionBar actionBar = mActivity.getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_trip_list, container, false);
}
#Override
public void onResume() {
super.onResume();
((HomeActivity) mActivity).setDrawerIndicatorEnabled(false);
}
Also, when I'm in second fragment I'm able to swipe and see the drawer menu. I don't want this behaviour, drawer menu should only open in fragment 1.
If any thing is wrong in my code please let me know.
Finally got the answer. In my scenario I'm disabling the drawer indicator by mActionBarDrawerToggle.setDrawerIndicatorEnabled(false); and due to this Navigation icon clicks got disabled. To enable this I've to add ToolbarNavigationClickListener to ActionBarDrawerToggle which will enable navigation icon clicks.
Below is the my working code :-
mActionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});
Refer this link for more clarification
After struggling with the same problem for ages, I eventually managed to get the Up button to work in fragments with this code.
You must have setHasOptionsMenu set up in onCreate() or onCreateView()
setHasOptionsMenu(true);
Then, in onOptionsItemSelected() add this check for the up / home button being pressed to your switch() [or if...] statement:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
x.L();
switch (item.getItemId()) {
case android.R.id.home :
getActivity().onBackPressed();
break;
case R.id.mn_exit :
exitFragment();
break;
default :
break;
}
return super.onOptionsItemSelected(item);
}

Issues in using new Toolbar component,hiding and showing Navigation drawer icon ,Home Up icon click event from fragments

I recently started updating my app to use the new Toolbar component introduced in Android 5.0 with navigation drawer. Flow of app is : MainActivity which has a toolbar, navigation drawer with menu 1. Home 2. Cart.
Home Menu navigates to "Home Detail" through a button in it.
Layout of "MainActivity" :
<LinearLayout 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"
android:orientation="vertical">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" />
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout android:id="#+id/activity_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ListView
android:id="#+id/left_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#android:color/white"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:listSelector="#android:color/transparent" />
</android.support.v4.widget.DrawerLayout>
I am adding two fragments HomeFragment,CartFragment on "MainActivity" on menu selected from drawer as below, default selection is position 0 i.e "Home"
class "MainActivity.java" ::
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTitle = mDrawerTitle = getTitle();
drawer = (DrawerLayout) findViewById(R.id.drawer);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
tvTitle = (TextView) mToolbar.findViewById(R.id.toolbar_title);
if (mToolbar != null) {
setSupportActionBar(mToolbar);
}
mDrawerToggle = new ActionBarDrawerToggle(this, drawer,mToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) {
public void onDrawerClosed(View view) {
getSupportActionBar().setTitle(mTitle);
}
public void onDrawerOpened(View drawerView) {
getSupportActionBar().setTitle(mDrawerTitle);
}
};
drawer.setDrawerListener(mDrawerToggle);
mDrawerList = (ListView) findViewById(R.id.left_drawer);
dataList = new ArrayList<DrawerItem>();
dataList.add(new DrawerItem(Constants.V_HOME, R.drawable.ic_launcher));
dataList.add(new DrawerItem(Constants.V_MY_CART, R.drawable.ic_launcher));
mDrawerList.setAdapter(adapterDrawer);
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
// to show first "Home fragment" on start up of application
if(savedInstanceState==null)
SelectItem(0);
}
public void SelectItem(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new HomeFragment();
replaceFragment(fragment, Constants.V_TAG_HOME,false,"Home");
break;
case 1:
fragment = new CartFragment();
replaceFragment(fragment, Constants.V_TAG_MY_CART,false,"My Cart");
break;
}
drawer.closeDrawer(mDrawerList);
}
public void replaceFragment(Fragment fragment,String fragment_tag,boolean showHome,String title){
frgManager = this.getSupportFragmentManager();
FragmentTransaction ft = frgManager.beginTransaction();
ft.replace(R.id.activity_frame,fragment,fragment_tag);
if(showHome)
ft.addToBackStack(null);
ft.commit();
shouldDisplayHomeUp(showHome);
}
public void shouldDisplayHomeUp(boolean showHome){
if(showHome){
mDrawerToggle.setDrawerIndicatorEnabled(false);
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}else{
mDrawerToggle.setDrawerIndicatorEnabled(true);
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
getSupportActionBar().setHomeButtonEnabled(false);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId())
{
case android.R.id.home:
Toast.makeText(getApplicationContext(),"main act clicked", Toast.LENGTH_SHORT).show();
return false;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
if(frgManager.getBackStackEntryCount()>0){
getSupportFragmentManager().popBackStack();
// show the drawer icon when on moving back
shouldDisplayHomeUp(false);
}else{
super.onBackPressed();
}
mDrawerToggle.syncState();
}
My home fragment has button "Detail" on click of button,replaces to other fragment :"HomeDetailFragment"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="#+id/btnDetail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Home detail" />
<FrameLayout
android:id="#+id/home_frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
class "HomeFragment.java" btnDetail click event which replace to other fragment "HomeDetailFragment"::
btnDetail.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Fragment fragment = new HomeDetailFragment();
((MainActivity)getActivity()).showDrawerIndicator(false);
FragmentManager frManager = getActivity().getSupportFragmentManager();
FragmentTransaction ft = frManager.beginTransaction();
ft.addToBackStack(null);
ft.replace(R.id.activity_frame, fragment).commit();
}
});
class "HomeDetailFragment.java" ::
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
// update the actionbar to show the up carat/affordance
((MainActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// TODO Auto-generated method stub
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// your code for order here
Toast.makeText(getActivity(), "home detail", Toast.LENGTH_LONG).show();
((MainActivity)getActivity()).onBackPressed();
return true;
}
return true;
}
My problems ::
1. In "HomeDetailFragment", I can see the "UP home icon" but cannot get the click event of home icon onOptionsItemSelected not being called, so cant navigate back to HomeFragment
2. When pressing the Phone Back Button, and again navigating to "Home Detail" it is not showing "UP home icon"
Please guide me.
In "HomeDetailFragment", I can see the "UP home icon" but cannot get the click event of home icon onOptionsItemSelected not being called, so cant navigate back to HomeFragment
One way to achieve this is by using the Toolbar from your MainActivity like so:
Toolbar mToolbar= ((MainActivity)getActivity()).mToolbar;
mToolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_nav_back));
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("MrE", "home selected");
}
});
When pressing the Phone Back Button, and again navigating to "Home Detail" it is not showing "UP home icon"
The reason your code isn't getting called is because it is in the onCreate of your Fragment. Move it to the onCreateOptionsMenu instead to have it update.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Put toolbar stuff from above here
super.onCreateOptionsMenu(menu, inflater);
}
I had the exact issue.
Use the setToolbarNavigationClickListener method.
In MainActivity.java,
actionBarToggle.setToolbarNavigationClickListener(new View.OnClickListener({
#Override
public void onClick(View v) {
MainActivity.this.onSupportNavigateUp();
}
});
Avoid implementing Up Navigation individually in Fragments.
You called getSupportActionBar().setDisplayHomeAsUpEnabled(true) which shows the button in the toolbar but doesn't activate it.
Calling getSupportActionBar().setHomeButtonEnabled(true); in addition should do the job.
You show the back-button in the toolbar from within the Fragment which is something I would avoid. Try moving this part to your Activity, when you do the FragmentTransaction.

Cannot catch toolbar home button click event

I've implemented the newest appcompat library and using the Toolbar as action bar. But the problem is I cannot catch the home button / hamburger icon click event. I've tried and looked everything but doesn't seem to find a similar problem.
This is my Activity class :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Set up the drawer.
navDrawerFragment =
(NavigationDrawerFragment) getSupportFragmentManager()
.findFragmentById(R.id.navigation_drawer);
navDrawerFragment.setUp(
R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout),
toolbar);
}
And this is my NavigationDrawerFragment class :
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
currentSelectedPosition = savedInstanceState.getInt(
STATE_SELECTED_POSITION);
fromSavedInstanceState = true;
}
// Select either the default item (0) or the last selected item.
selectItem(currentSelectedPosition);
}
#Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Indicate that this fragment would like
// to influence the set of actions in the action bar.
setHasOptionsMenu(true);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
drawerListView = (ListView) inflater.inflate(
R.layout.fragment_navigation_drawer, container, false);
drawerListView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent,
View view, int position, long id) {
selectItem(position);
}
});
//mDrawerListView.setAdapter();
//mDrawerListView.setItemChecked(mCurrentSelectedPosition, true);
return drawerListView;
}
public void setUp(int fragmentId, DrawerLayout drawerLayout, Toolbar toolbar) {
fragmentContainerView = getActivity().findViewById(fragmentId);
this.drawerLayout = drawerLayout;
// set a custom shadow that overlays the main
// content when the drawer opens
drawerLayout.setDrawerShadow(
R.drawable.drawer_shadow, GravityCompat.START);
// set up the drawer's list view
// with items and click listener
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the navigation drawer and the action bar app icon.
drawerToggle = new ActionBarDrawerToggle(
getActivity(),
drawerLayout,
toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close) {
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
}
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
};
// If the user hasn't 'learned' about the drawer,
// open it to introduce them to the drawer,
// per the navigation drawer design guidelines.
if (!userLearnedDrawer && !fromSavedInstanceState) {
drawerLayout.openDrawer(fragmentContainerView);
}
// Defer code dependent on restoration of previous instance state.
drawerLayout.post(new Runnable() {
#Override
public void run() {
drawerToggle.syncState();
}
});
drawerLayout.setDrawerListener(drawerToggle);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(STATE_SELECTED_POSITION, currentSelectedPosition);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Forward the new configuration the drawer toggle component.
drawerToggle.onConfigurationChanged(newConfig);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.d("cek", "item selected");
if (drawerToggle.onOptionsItemSelected(item)) {
Log.d("cek", "home selected");
return true;
}
return super.onOptionsItemSelected(item);
}
when I clicked a menu item, the log "item selected" gets called. But when I click on the home button, it opens navigation drawer but the log "home selected" never get called. I've set onOptionsItemSelected method inside my Activity as well, but it still doesn't get called.
If you want to know when home is clicked is an AppCompatActivity then you should try it like this:
First tell Android you want to use your Toolbar as your ActionBar:
setSupportActionBar(toolbar);
Then set Home to be displayed via setDisplayShowHomeEnabled like this:
getSupportActionBar().setDisplayShowHomeEnabled(true);
Finally listen for click events on android.R.id.home like usual:
#Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
if (menuItem.getItemId() == android.R.id.home) {
Timber.d("Home pressed");
}
return super.onOptionsItemSelected(menuItem);
}
If you want to know when the navigation button is clicked on a Toolbar in a class other than AppCompatActivity you can use these methods to set a navigation icon and listen for click events on it. The navigation icon will appear on the left side of your Toolbar where the the "home" button used to be.
toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_nav_back));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("cek", "home selected");
}
});
If you want to know when the hamburger is clicked and when the drawer opens, you're already listening for these events via onDrawerOpened and onDrawerClosed so you'll want to see if those callbacks fit your requirements.
mActionBarDrawerToggle = mNavigationDrawerFragment.getActionBarDrawerToggle();
mActionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// event when click home button
}
});
in mycase this code work perfect
This is how I do it to return to the right fragment otherwise if you have several fragments on the same level it would return to the first one if you donĀ“t override the toolbar back button behavior.
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish();
}
});
I think the correct solution with support library 21 is the following
// action_bar is def resource of appcompat;
// if you have not provided your own toolbar I mean
Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
if (toolbar != null) {
// change home icon if you wish
toolbar.setLogo(this.getResValues().homeIconDrawable());
toolbar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//catch here title and home icon click
}
});
}
I have handled back and Home button in Navigation Drawer like
public class HomeActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private ActionBarDrawerToggle drawerToggle;
private DrawerLayout drawerLayout;
NavigationView navigationView;
private Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
resetActionBar();
navigationView = (NavigationView) findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(this);
//showing first fragment on Start
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).replace(R.id.content_fragment, new FirstFragment()).commit();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
//listener for home
if(id==android.R.id.home)
{
if (getSupportFragmentManager().getBackStackEntryCount() > 0)
onBackPressed();
else
drawerLayout.openDrawer(navigationView);
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onBackPressed() {
if (drawerLayout.isDrawerOpen(GravityCompat.START))
drawerLayout.closeDrawer(GravityCompat.START);
else
super.onBackPressed();
}
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Begin the transaction
Fragment fragment = null;
// Handle navigation view item clicks here.
int id = item.getItemId();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (id == R.id.nav_companies_list) {
fragment = new FirstFragment();
// Handle the action
}
// Begin the transaction
if(fragment!=null){
if(item.isChecked()){
if(getSupportFragmentManager().getBackStackEntryCount()==0){
drawer.closeDrawers();
}else{
removeAllFragments();
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE).replace(R.id.WikiCompany, fragment).commit();
drawer.closeDrawer(GravityCompat.START);
}
}else{
removeAllFragments();
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE).replace(R.id.WikiCompany, fragment).commit();
drawer.closeDrawer(GravityCompat.START);
}
}
return true;
}
public void removeAllFragments(){
getSupportFragmentManager().popBackStackImmediate(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
public void replaceFragment(final Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.replace(R.id.WikiCompany, fragment).addToBackStack("")
.commit();
}
public void updateDrawerIcon() {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
try {
Log.i("", "BackStackCount: " + getSupportFragmentManager().getBackStackEntryCount());
if (getSupportFragmentManager().getBackStackEntryCount() > 0)
drawerToggle.setDrawerIndicatorEnabled(false);
else
drawerToggle.setDrawerIndicatorEnabled(true);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}, 50);
}
public void resetActionBar()
{
//display home
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
}
public void setActionBarTitle(String title) {
getSupportActionBar().setTitle(title);
}
}
and In each onViewCreated I call
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
((HomeActivity)getActivity()).updateDrawerIcon();
((HomeActivity) getActivity()).setActionBarTitle("List");
}
This is how I implemented it pre-material design and it seems to still work now I've switched to the new Toolbar. In my case I want to log the user in if they attempt to open the side nav while logged out, (and catch the event so the side nav won't open). In your case you could not return true;.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (!isLoggedIn() && item.getItemId() == android.R.id.home) {
login();
return true;
}
return mDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
}
I changed the DrawerLayout a bit to get the events and be able to consume and event, such as if you want to use the actionToggle as back if you are in detail view:
public class ListenableDrawerLayout extends DrawerLayout {
private OnToggleButtonClickedListener mOnToggleButtonClickedListener;
private boolean mManualCall;
public ListenableDrawerLayout(Context context) {
super(context);
}
public ListenableDrawerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListenableDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* Sets the listener for the toggle button
*
* #param mOnToggleButtonClickedListener
*/
public void setOnToggleButtonClickedListener(OnToggleButtonClickedListener mOnToggleButtonClickedListener) {
this.mOnToggleButtonClickedListener = mOnToggleButtonClickedListener;
}
/**
* Opens the navigation drawer manually from code<br>
* <b>NOTE: </b>Use this function instead of the normal openDrawer method
*
* #param drawerView
*/
public void openDrawerManual(View drawerView) {
mManualCall = true;
openDrawer(drawerView);
}
/**
* Closes the navigation drawer manually from code<br>
* <b>NOTE: </b>Use this function instead of the normal closeDrawer method
*
* #param drawerView
*/
public void closeDrawerManual(View drawerView) {
mManualCall = true;
closeDrawer(drawerView);
}
#Override
public void openDrawer(View drawerView) {
// Check for listener and for not manual open
if (!mManualCall && mOnToggleButtonClickedListener != null) {
// Notify the listener and behave on its reaction
if (mOnToggleButtonClickedListener.toggleOpenDrawer()) {
return;
}
}
// Manual call done
mManualCall = false;
// Let the drawer layout to its stuff
super.openDrawer(drawerView);
}
#Override
public void closeDrawer(View drawerView) {
// Check for listener and for not manual close
if (!mManualCall && mOnToggleButtonClickedListener != null) {
// Notify the listener and behave on its reaction
if (mOnToggleButtonClickedListener.toggleCloseDrawer()) {
return;
}
}
// Manual call done
mManualCall = false;
// Let the drawer layout to its stuff
super.closeDrawer(drawerView);
}
/**
* Interface for toggle button callbacks
*/
public static interface OnToggleButtonClickedListener {
/**
* The ActionBarDrawerToggle has been pressed in order to open the drawer
*
* #return true if we want to consume the event, false if we want the normal behaviour
*/
public boolean toggleOpenDrawer();
/**
* The ActionBarDrawerToggle has been pressed in order to close the drawer
*
* #return true if we want to consume the event, false if we want the normal behaviour
*/
public boolean toggleCloseDrawer();
}
}
The easiest approach we could do is change the home icon to a known icon and compare drawables (because android.R.id.home icon can differ to different api versions
so set a toolbar as actionbar
SetSupportActionBar(_toolbar);
_toolbar.NavigationIcon = your_known_drawable_here;
for (int i = 0; i < _toolbar.ChildCount; i++)
{
View v = _toolbar.GetChildAt(i);
if (v is ImageButton)
{
ImageButton imageButton = v as ImageButton;
if (imageButton.Drawable.GetConstantState().Equals(_bookMarkIcon.GetConstantState()))
{
//here v is the widget that contains the home icon you can add your click events here
}
}
}
In my case I had to put the icon using:
toolbar.setNavigationIcon(R.drawable.ic_my_home);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
And then listen to click events with default onOptionsItemSelected and android.R.id.home id
For anyone looking for a Xamarin implementation (since events are done differently in C#), I simply created this NavClickHandler class as follows:
public class NavClickHandler : Java.Lang.Object, View.IOnClickListener
{
private Activity mActivity;
public NavClickHandler(Activity activity)
{
this.mActivity = activity;
}
public void OnClick(View v)
{
DrawerLayout drawer = (DrawerLayout)mActivity.FindViewById(Resource.Id.drawer_layout);
if (drawer.IsDrawerOpen(GravityCompat.Start))
{
drawer.CloseDrawer(GravityCompat.Start);
}
else
{
drawer.OpenDrawer(GravityCompat.Start);
}
}
}
Then, assigned a custom hamburger menu button like this:
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
SupportActionBar.SetDefaultDisplayHomeAsUpEnabled(false);
this.drawerToggle.DrawerIndicatorEnabled = false;
this.drawerToggle.SetHomeAsUpIndicator(Resource.Drawable.MenuButton);
And finally, assigned the drawer menu toggler a ToolbarNavigationClickListener of the class type I created earlier:
this.drawerToggle.ToolbarNavigationClickListener = new NavClickHandler(this);
And then you've got a custom menu button, with click events handled.
Try this code
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == android.R.id.home){
//You can get
}
return super.onOptionsItemSelected(item);
}
Add below code to your onCreate() metod
ActionBar ab = getSupportActionBar();
ab.setDisplayHomeAsUpEnabled(true);
Apart from the answer provided by MrEngineer13, there is also another possible reason why the click event might not have been captured in the onOptionsSelected method. Your DrawerLayout may have overlayed your Toolbar's interface component in the layout XML file. Therefore, whenever you attempt to click the Home button, you're only clicking the DrawerLayout, but not the Home button that's located beneath it.
All you have to do now is rearrange your Toolbar in the corresponding layout XML file so that it is not blocked by any other UI component.
Programmatically, I did attempt to call the bringToFront() method on the toolbar (toolbar.bringToFront()). However, in my app's context, it does not seem to be the solution.

Categories

Resources