I have two fragments FragmentHome and FragmentAbout, I have added NavigationDrawer to app when I click Home it opens FragmentHome and About opens FragmentAbout, when I open FragmentAbout I am also adding it to backstack. This is working fine.
Now the problem is when I click on About and press back button it goes to the FragmentHome but the NavigationDrawer still shows the About as selected item, I want to change this selected item to Home when I press back button from FragmentAbout
Home Activity:
public class ActivityHome extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
Toolbar toolbar;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
// Toolbar
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Drawer layout
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.nav_drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.nav_drawer_open, R.string.nav_drawer_close);
assert drawer != null;
drawer.setDrawerListener(toggle);
toggle.syncState();
// Navigation view
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
assert navigationView != null;
navigationView.setNavigationItemSelectedListener(this);
// Open first menu item
navigationView.getMenu().performIdentifierAction(R.id.nav_home, 0);
// Set first item checked
navigationView.setCheckedItem(R.id.nav_home);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
final MenuItem menuItem = item;
// Check if menu item is selected
if (item.isChecked())
item.setChecked(false);
else
item.setChecked(true);
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_home) {
// Open home fragment
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame_layout, new FragmentHome())
.commit();
} else if (id == R.id.nav_about) {
toolbar.setTitle("About");
// Open home fragment
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame_layout, new FragmentAbout())
.addToBackStack(null)
.commit();
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.nav_drawer_layout);
assert drawer != null;
drawer.closeDrawer(GravityCompat.START);
return true;
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.nav_drawer_layout);
assert drawer != null;
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}}
FragmentHome
public class FragmentHome extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_home, container, false);
}
#Override
public void onResume() {
super.onResume();
((AppCompatActivity)getActivity()).getSupportActionBar().setTitle(R.string.fragment_home_title);
}
}
FragmentAbout code is same as FragmentHome just layout change.
I have searched a lot on stackoverflow but didn't find any solution yet, so if someone know how to do this please tell me.
There is a OnBackStackChangedListener that you can use for this. Tried it and it works great.
public Fragment getCurrentFragment() {
return this.getSupportFragmentManager().findFragmentById(R.id.fragment_container);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
...
this.getSupportFragmentManager().addOnBackStackChangedListener(
new FragmentManager.OnBackStackChangedListener() {
public void onBackStackChanged() {
Fragment current = getCurrentFragment();
if (current instanceof MyFragmentA) {
navigationView.setCheckedItem(R.id.nav_myfragA);
} else {
navigationView.setCheckedItem(R.id.nav_myfragB);
}
}
});
...
}
This might not be a good solution, but at least it is acceptable for me. You need to store fragment's position inside stack variable (ex: List) whenever a fragment menu is clicked from nav drawer. Then override onBackPressed to remove the last value from stack, and set drawer position to the current last value of stack. Here's the example:
private List<Integer> itemPositionStacks = new ArrayList<>();
protected void onCreate(#Nullable Bundle savedInstanceState) {
itemPositionStacks.add(currentSelectedPosition);
}
public void onNavigationViewItemSelected(int itemId) {
Fragment fr = null;
switch (itemId) {
case 0:
fr = new aFragment();
break;
case 1:
fr = new bFragment();
break;
}
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, fr)
.addToBackStack(null)
.commit();
Drawer.getInstance().setDrawerChecked(itemId);
itemPositionStacks.add(itemId);
}
public void onBackPressed() {
if(itemPositionStacks.size() > 1) {
itemPositionStacks.remove(itemPositionStacks.size() - 1);
Drawer.getInstance().setDrawerChecked(itemIdStacks.get(itemIdStacks.size() - 1));
}
super.onBackPressed();
}
In your onBackPressed() function ..
you must choose which item to be selected by using
drawer.setCheckedItem(R.id.nav_home);
and remove the selection of the another item
drawer.getMenu().findItem(R.id.nav_about).setChecked(false);
Related
I am using navigation drawer with fragments and in my Home page i am navigating like this==> maincategory===>subcategory===>subcategoryDetail
while moving from maincategory to subcategory it perfectly replaces the hamburger icon and shows back arrow icon and onback press is working perfectly
but while moving from subcategory to subcategoryDetail when i press the back arrow of subcategoryDetail onback press is working perfectly
but it replaces the back arrow of subcategory.java page with hamburger icon and i cannot go back to home page
MainActivity.java
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
Toolbar toolbar;
DrawerLayout drawer;
ActionBarDrawerToggle toggle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
displaySelectedScreen(R.id.nav_home);
}
public ActionBarDrawerToggle getToggle() {
return toggle;
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
int fragments = getSupportFragmentManager().getBackStackEntryCount();
if (fragments == 1) {
finish();
} else if (getFragmentManager().getBackStackEntryCount() > 1) {
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
toggle.setDrawerIndicatorEnabled(true);
}
}
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
displaySelectedScreen(item.getItemId());
return true;
}
private void displaySelectedScreen(int itemId) {
Bundle bundle = new Bundle();
//creating fragment object
Fragment fragment = null;
//initializing the fragment object which is selected
switch (itemId) {
case R.id.nav_home:
fragment = new HomeFragment();
break;
case R.id.nav_mens_clothing:
bundle.putString("MAINCATEGORYID", String.valueOf(1));
bundle.putString("MAINCATEGORYNAME","Carpentry");
fragment = new SubCategoryFragment();
fragment.setArguments(bundle);
break;
case R.id.nav_womens_clothing:
bundle.putString("MAINCATEGORYID", String.valueOf(2));
bundle.putString("MAINCATEGORYNAME","Electrical");
fragment = new SubCategoryFragment();
fragment.setArguments(bundle);
break;
case R.id.nav_boys_clothing:
fragment = new SubCategoryFragment();
break;
}
//replacing the fragment
if (fragment != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack(null);
ft.commit();
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
}
}
SubCategoryFragment.java
public class SubCategoryFragment extends Fragment {
protected Toolbar toolbar;
protected ActionBarDrawerToggle toggle;
View view;
public SubCategoryFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (view == null) {
view = inflater.inflate(R.layout.fragment_sub_category, container, false);
toolbar = ((MainActivity) getActivity()).findViewById(R.id.toolbar);
toggle = ((MainActivity) getActivity()).getToggle();
shimmerContainer = view.findViewById(R.id.shimmer_view_container);
recyclerView_subcategory = view.findViewById(R.id.recycler_view_category);
toggle.setDrawerIndicatorEnabled(false);
toggle.setHomeAsUpIndicator(R.drawable.back);
toggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getActivity().onBackPressed();
}
});
}
return view;
}
#Override
public void onPause() {
super.onPause();
toolbar.setTitle("Cooper");
toggle.setDrawerIndicatorEnabled(true);
}
SubCategoryDetailFragment.java
public class SubCategoryDetailFragment extends Fragment {
protected Toolbar toolbar;
protected ActionBarDrawerToggle toggle;
View view;
public SubCategoryDetailFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (view == null) {
view = inflater.inflate(R.layout.fragment_sub_category_detail, container, false);
toolbar = ((MainActivity) getActivity()).findViewById(R.id.toolbar);
toggle = ((MainActivity) getActivity()).getToggle();
toggle.setDrawerIndicatorEnabled(false);
toggle.setHomeAsUpIndicator(R.drawable.back);
toggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getActivity().onBackPressed();
}
});
}
return view;
}
#Override
public void onPause() {
super.onPause();
toolbar.setTitle("zzz");
toggle.setDrawerIndicatorEnabled(true);
}}
}
Design two different toolbars in XML and set their visibility according to fragment and activity. When Activity load set Toolbar with Navigation drawer, but when fragment load in that activity hide the current toolbar and replace with another toolbar XML with the back icon.
Do not forget to add toolbar code in onResume() method of the fragment.
Please add these two lines in onresume it will work.
toggle.setDrawerIndicatorEnabled(false);
toggle.setHomeAsUpIndicator(R.drawable.back);
I am using navigation menu in an Activity. When I click menu, it goes to particular fragment that time I give addtobackstack(null). I want to fix these 2 issues:
I want to show do you want to exit app through a popup In the back fragment
Assume that I traverse from Fragment A to B and then B to C. If I give back in the Fragment C I want to come the main page, without showing the Fragment B.
This is my Home Activity:
package school.wyse.app.activities;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
public class ParentHomeActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
ServerUtils servutil;
GridLayoutManager grid;
Toolbar toolbar;
private View navHeader;
LinearLayout profile;
ImageView msglist;
ArrayList<StudentProfile> lang_list_new;
public RecyclerView studentsListRecyclerView;
public ParentMenuDashoard mStudAdapter;
StudentProfile[] profiles;
private StudentProfile[] studentCachedData;
Context ctx;
DrawerLayout drawer;
ImageView imageViewstaff;
String tenent_id,profilename,image,userphone;
Integer id,roleid;
String backStateName;
TextView profile_phone,profile_name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
setContentView(R.layout.activity_parent_home);
backStateName = this.getClass().getName();
ctx=this;
Toast.makeText(ctx, "backStateName--"+backStateName, Toast.LENGTH_SHORT).show();
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
navHeader=navigationView.getHeaderView(0);
studentsListRecyclerView = (RecyclerView) navHeader.findViewById(R.id.messageWindowRecycler);
ParentDashboard parentDashboard = new ParentDashboard();
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.content_frame, parentDashboard, parentDashboard.getTag()).commit();
toolbar.setTitle("Dashboard");
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onBackPressed() {
try {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.home, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// 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.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
/* if (id == R.id.action_msg) {
return true;
}*/
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_dashboard) {
ParentDashboard parentDashboard = new ParentDashboard();
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.content_frame, parentDashboard, parentDashboard.getTag()).addToBackStack(null).commit();
//toolbar.setTitle("Dashboard");
} else if (id == R.id.nav_teachers) {
TeacherList teacherList = new TeacherList();
FragmentManager manager = getSupportFragmentManager();
// manager.beginTransaction().replace(R.id.id_content_frame, accountsMenuListFragment, "AccountsMenu").addToBackStack(" ").commit();
manager.beginTransaction().replace(R.id.content_frame, teacherList, teacherList.getTag()).addToBackStack(null).commit();
// toolbar.setTitle("Teachers");
} else if (id == R.id.nav_attendance) {
AttendanceFragment attendanceFragment = new AttendanceFragment();
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.content_frame, attendanceFragment, attendanceFragment.getTag()).addToBackStack(null).commit();
// toolbar.setTitle("Attendance");
} else if (id == R.id.nav_consumablity) {
ParentConsumablityFragment parentConsumablityFragment = new ParentConsumablityFragment();
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.content_frame, parentConsumablityFragment, parentConsumablityFragment.getTag()).addToBackStack(null).commit();
// toolbar.setTitle("Attendance");
}
else {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
Okay, sorry for late reply
This part goes in onBackPressed() of your activity, which basically check if you have fragments attached (so it won't perform the native back, which closes the app)
if (childFragments.size() > 0) {
if (childFragments.get((childFragments.size() - 1)) != null) {
childFragments.remove(childFragments.size() - 1);
return;
}
}
All you have to do is add/remove items to this array every time you attach / detach fragments :)
For your particular case when you are on fragment C and want to go back to fragment A without showing fragment B, I suggest you make a public function that remove all fragments from ArrayList except last one (from position 0)
Use below code in mainactivity where you want to show appexit:
#Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
finish();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
}
When moving fragment A to B do not add "addbackstack". When moving fragment B to C add "addbackstack("C")"
first of all, you have to take care of your second issue as it will lead to easy handle for the first issue, hence you have to take care of how to initiate the fragments in order to always coming to the first fragment while hitting back regardless the flow of fragments that lead to the current fragment, to do so, just initiate the fragments like the following:
/**
* To initiate any fragment
*/
private void showAnyFragment(Fragment fragmentToShow) {
getSupportFragmentManager().popBackStack();
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.content);
frameLayout.setVisibility(View.VISIBLE);
getSupportFragmentManager().beginTransaction()
.replace(R.id.content, fragmentToShow)
.addToBackStack(null)
.commit();
}
/**
* When (for a reason) you want to initiate the main fragment (FragmentA)
*/
private void homeClicked() {
getSupportFragmentManager().popBackStack();
}
Now, fragmentA is your main fragment, when going from A to B to C to D and click back button it will go back to A directly.
Coming to your second issue, it will be straight forward as you already keeping only fragmentA always in the back stack, so onBackPressed() function of the Activity will not be called unless there are No other fragment other than FragmentAis being displayed(e.g if you are in fragmentC and you click back button, the onBackPressed() function will not be called), so you are sure that when you come inside onBackPressed() function of the activity that the currently running fragment is FragmentA which is your main page fragment.
so if you want to display a popup while the user trying to exit the app (he would be in FragmentA and hiitting Back), all you have to do is to override the onBackPressed() method of the MainActivity that holds the fragments:
#Override
public void onBackPressed() {
// the user here is in FragmentA(main page),
and he is clicking back to exit the app.
// TODO show popup here or do whatever you want
}
Hey I'm new in android development and i'm trying to develop an app with navigation drawer. So i created fragments with navigation drawer menus, and from one of those fragments I have given an intent to a new activity. But i dont know how to go back from that activity to previous fragment.
MainActivity.java
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
displaySelectedScreen(R.id.nav_bus);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void displaySelectedScreen(int itemId) {
Fragment fragment = null;
switch (itemId) {
case R.id.nav_bus:
fragment = new BusFragment();
break;
case R.id.nav_hotel:
fragment = new HotelFragment();
break;
}
if (fragment != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.commit();
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
displaySelectedScreen(item.getItemId());
return true;
}
}
From this fragment i have given intent to city.java activity
HotelFragment.java
public class HotelFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView= inflater.inflate(R.layout.fragment_hotel, container, false);
Button button = (Button) rootView.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
updateDetail();
} });
return rootView;
}
public void updateDetail() {
Intent intent = new Intent(getActivity(), City.class);
startActivity(intent);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getActivity().setTitle("Hotel");
}
}
City.java
public class City extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_city_list);
} }
In manifest file i have added this
<activity android:name=".City_List"
android:parentActivityName = "MainActivity"
>
<meta-data
android:name = "android.support.PARENT_ACTIVITY"
android:value = "MainActivity" />
</activity>
</application>
to be able to go back to the previous fragment should include the .addToBackStack()
if (fragment != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackstack(null)
ft.commit();
}
and when you click on back button in the toolbar programmatically go back to the previous fragment using following code.
if ( getFragmentManager().getBackStackEntryCount() > 0)
{
getFragmentManager().popBackStack();
return;
}
super.onBackPressed();
Add this line inside back pressed method
if(getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
}
else {
super.onBackPressed();
}
Currently Used Google Navigation Drawer, having some problem when user backpress.
When user backpress, they didn't update menu Item
Example When I click the App. The sequence are A>B>C>B>C ,if I backpress I wanted to be C>B>A. How should I code this way out ?
My code
public class MainActivity extends AppCompatActivity {
private String appTitle;
private Toolbar toolbar;
private NavigationView navigationView;
private DrawerLayout drawerLayout;
private TextView toolbarTitle;
private Fragment fragment;
private FragmentManager fragmentManager;
private Title title;
private MenuItem menuItem2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Actionbar
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbarTitle = (TextView) toolbar.findViewById(R.id.toolbar_title);
toolbarTitle.setTextColor(Color.parseColor("#FFFFFF"));
setTitle("");
fragmentManager = getSupportFragmentManager();
fragment= new HomeFragment();
title = new Title(getApplicationContext());
fragmentManager.beginTransaction().replace(R.id.content_frame,fragment , title.getStrHome()).commit();
navigationView = (NavigationView) findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItem2 = menuItem;
menuItem.setChecked(true);
drawerLayout.closeDrawers();
if (menuItem.getItemId() == R.id.nav_home) {
fragment = new HomeFragment();
appTitle = title.getStrHome();
} else if ((menuItem.getItemId() == R.id.nav_direction)) {
fragment = new DirectionFragment();
appTitle = title.getStrDirection();
} else if ((menuItem.getItemId() == R.id.nav_more)) {
fragment = new MoreFragment();
appTitle = title.getStrMore();
} else if((menuItem.getItemId()==R.id.nav_directory)){
fragment = new DirectoryFragment();
appTitle = title.getStrDirectory();
}
else {
Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_SHORT).show();
}
replaceFragment(fragment,appTitle);
return true;
}
});
drawerLayout = (DrawerLayout) findViewById(R.id.drawer);
ActionBarDrawerToggle actionBarDrawerToggle =
new ActionBarDrawerToggle
(this,drawerLayout,toolbar,R.string.drawer_open,R.string.drawer_close){
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
}
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
};
drawerLayout.setDrawerListener(actionBarDrawerToggle);
actionBarDrawerToggle.syncState();
}
public void onBackPressed() {
if(drawerLayout.isDrawerOpen(GravityCompat.START)){
drawerLayout.closeDrawer(GravityCompat.START);
}
else {
if (fragmentManager.getBackStackEntryCount() > 0 ){
fragmentManager.popBackStack();
toolbarTitle.setText(appTitle);
menuItem2.setChecked(true);
} else {
finish();
}
}
}
public void replaceFragment(Fragment fragment, String tag){
toolbarTitle.setText(tag);
FragmentTransaction ft = fragmentManager.beginTransaction().replace(R.id.content_frame, fragment, tag);
ft.addToBackStack(tag);
ft.commit();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
As stated on the official page on Android tasks and back stack you can see how you can accomplish your desired behaviour using the FLAG_ACTIVITY_CLEAR_TOP in your Intent flags. This picture demonstrates it very well.
Your regular back button proceeds as:
When you specify this flag, you get a behavior like you need
Edit:
The official documentation states:
FLAG_ACTIVITY_CLEAR_TOP
If the activity being started is already running in the current task, then instead of launching a new instance of that activity, all of the
other activities on top of it are destroyed
This means, there will be no duplicates of your different Activities, and you will have a clean Back Stack.
In your example A>B>C>B>C would not be possible. Instead it would be A>B>C, since B and C already exist in the stack, they will not be added, but replaced instead.
Study the Android Activity Launch Mode.
here is the clear Explanation available.
Just take a look.
I have created MainActivity with NavigationView. When Activity is opened I want to automatically select the first item in the navigation drawer and open Fragment under that item. I've searched a lot but didn't find any proper solutions.
What is the proper way to do this ?
Main Activity:
public class MainActivity extends AppCompatActivity implements Config {
private NavigationView navigationView;
private DrawerLayout drawerLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setTitleTextColor(getResources().getColor(R.color.colorIcons));
if (null != getSupportActionBar())
getSupportActionBar().setLogo(R.drawable.ic_blogger_white);
//Start PostListFragmentWebView
/*PostListFragmentWebView postListFragmentWebView = new PostListFragmentWebView();
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame, postListFragmentWebView)
.commit();*/
//Initializing NavigationView
navigationView = (NavigationView) findViewById(R.id.navigationView);
//Setting Navigation View Item Selected Listener to handle the item click of the navigation menu
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
//Checking if the item is in checked state or not, if not set it to checked state.
if (menuItem.isChecked()) menuItem.setChecked(false);
else menuItem.setChecked(true);
//Closing drawer on item click
drawerLayout.closeDrawers();
//Check to see which item was clicked and perform the appropriate action.
switch (menuItem.getItemId()) {
case R.id.posts:
PostListFragmentWebView postListFragment = new PostListFragmentWebView();
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame, postListFragment)
.commit();
return true;
case R.id.pages:
PageListFragmentWebView pagetListFragment = new PageListFragmentWebView();
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame, pagetListFragment)
.commit();
return true;
case R.id.blog:
BlogInfoFragmentWebView blogInfoFragment = new BlogInfoFragmentWebView();
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame, blogInfoFragment)
.commit();
return true;
default:
Toast.makeText(getApplicationContext(), getResources().getString(R.string.drawer_error), Toast.LENGTH_SHORT).show();
return true;
}
}
});
// Initializing Drawer Layout and ActionBarToggle
drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.open_drawer, R.string.close_drawer) {
#Override
public void onDrawerClosed(View drawerView) {
// Code here will be triggered once the drawer closes as we don't want anything to happen so we leave this blank.
super.onDrawerClosed(drawerView);
}
#Override
public void onDrawerOpened(View drawerView) {
// Code here will be triggered once the drawer open as we dont want anything to happen so we leave this blank.
super.onDrawerOpened(drawerView);
}
};
//Setting the actionbarToggle to drawer layout
drawerLayout.setDrawerListener(actionBarDrawerToggle);
drawerLayout.getChildAt(0).setSelected(true);
//calling sync state is necessary or else your hamburger icon wont show up
actionBarDrawerToggle.syncState();
}
}
In onCreate(), following code will load the first item's fragment upon first start:
if (savedInstanceState == null) {
navigationView.getMenu().performIdentifierAction(R.id.posts, 0);
}
Thanks to calvinfly for this comment.
Add android:checked="true" to your first menu item.
And manually select one item, using
getSupportFragmentManager().beginTransaction().replace(R.id.frame, postListFragment).commit();
to open fragment.
Instead of normal listener ...
navView.setNavigationItemSelected(new Navigation.View.OnNavigationItemSelectedListener() {bla, bla, bla})
Create the listener as an Obj:
NavigationView.OnNavigationItemSelectedListener navViewListener;
navView.setNavigationItemSelectedListener(navViewListener = new NavigationView.OnNavigationItemSelectedListener() {bla, bla, bla})
...and use the Obj to trigger the listener event:
navViewListener.onNavigationItemSelected(navView.getMenu().getItem(0));
...where getItem(0) is the first menu item.
Use a method getItem(0).setChecked(true) or android:checked="true" at its menu item XML definition.
You could also use navigationView.setCheckedItem(R.id.default)(javadoc) after you setup your navigationview.
just add this code in onCreate method:
FragmentTransaction ftrans = getFragmentManager().beginTransaction();
ftrans.replace(R.id.container, <yourfragment>).commit();
Work for me !
This can be done even better while considering orientation and other configuration changes. We could select whatever nav drawer menuitem depending on whether we are coming from a previous state. Check: For the Navigation drawer wielding Activity:-
public static final String SELECTED_NAV_MENU_KEY = "selected_nav_menu_key";
// The selected grid position
private int mSelectedNavMenuIndex = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
...........................................................
navigationView.setNavigationItemSelectedListener(this);
if (savedInstanceState != null) {
// Recover assets
mSelectedNavMenuIndex = savedInstanceState.getInt(SELECTED_NAV_MENU_KEY);
// Recover menu as selected
MenuItem menuItem = navigationView.getMenu().getItem(mSelectedNavMenuIndex);
toggleNavMenuItemCheck(menuItem);
navigationView.getMenu().performIdentifierAction(menuItem.getItemId(), mSelectedNavMenuIndex);
return;
} else {
MenuItem menuItem = navigationView.getMenu().getItem(mSelectedNavMenuIndex);
toggleNavMenuItemCheck(menuItem);
navigationView.getMenu().performIdentifierAction(menuItem.getItemId(), mSelectedNavMenuIndex);
}
}
The toggle method that helps uncheck or check the menu item
private void toggleNavMenuItemCheck(MenuItem menuItem) {
if (menuItem.isChecked()){
menuItem.setChecked(false);
} else {
menuItem.setChecked(true);
}
}
This is how I save the state of the selected menu item. Check:-
#Override
public boolean onNavigationItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.nav_explore:
showExploreFragment(null);
mSelectedNavMenuIndex = 0;
break;
case R.id.nav_orders:
mSelectedNavMenuIndex = 1;
break;
case R.id.nav_settings:
mSelectedNavMenuIndex = 2;
break;
default:
showExploreFragment(null);
mSelectedNavMenuIndex = 0;
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
// Save any important data for recovery
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(SELECTED_NAV_MENU_KEY, mSelectedNavMenuIndex);
}
NB: The line with code:
navigationView.getMenu().performIdentifierAction(menuItem.getItemId(), mSelectedNavMenuIndex);
Can be replaced by the code:
onNavigationItemSelected(menuItem);
in menu.xml remember to mention android:checkable="true" for single item and android:checkableBehavior="single" for a group of items.
<item
android:id="#+id/pos_item_help"
android:checkable="true"
android:title="Help" />
<group
android:id="#+id/group"
android:checkableBehavior="single">
<item
android:id="#+id/menu_nav_home"
android:icon="#drawable/ic_home_black_24dp"
android:title="#string/menu_nav_home" />
</group>
then inside NavigationItemSelectedListener use setCheckedItem(R.id.item_id_in_menu) to make it selected.
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.pos_item_pos:
navigationView.setCheckedItem(R.id.pos_item_pos);
break;
case R.id.pos_item_orders:
navigationView.setCheckedItem(R.id.pos_item_orders);
break;
default:
}
return true;
}
And you do not have to do the dirty task of managing the selected item anymore. navigationView manages it by self.
1.) To land to the HomeFragment initially, use this inside your onCreate() in MainActivity:
Fragment fragment = new HomeFragment();
// replacing the fragment
if (fragment != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.commit();
}
2.) To set the item as selected in navigationDrawer set the item as checked in navigation_menu.xml
android:checked = "true"