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
This question is related to
android
android-actionbar
navigation-drawer
android-fragmentactivity
android-toolbar
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 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;
}
(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)
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.
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);
}
});
}
}
});
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");
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.
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" />
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.
Source: Stackoverflow.com