How to change the home menu in bottom navigation layout in Android - android

I have added three menus in BottomNavigationLayout
How can I open Center menu by default on startup?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz);
loadFragment(new ProfileFragment());
BottomNavigationView navigation = findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
private void loadFragment(Fragment fragment) {
// load fragment
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragmentContainer, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
I used this to load the fragment and it also loads fragment associated with the center menu but on bottom navigation the first menu is selected.
I hope you understand my problem. if not then check the Clash Royale. in this game, the battle layout is the first pop-up at startup as well as battle menu selected in the bottom navigation.
If anyone knows how to do this please help me.
thanks in advance

Just Go for This mate ! Just Copy and paste in your editor and there you go!
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz);
// loadFragment(new ProfileFragment()); Removed this line
BottomNavigationView navigation = findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
// Added this line
navigation.setSelectedItemId(bottomNavigation.getMenu().getItem(1).getItemId());
}
private void loadFragment(Fragment fragment) {
// load fragment
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragmentContainer, fragment);
transaction.addToBackStack(null);
transaction.commit();
}

Inside onCreate() method call that fragment which you want to open first at time of app launching.
When you tap on bottom menus you are performing some action for change the color of menu with fragment, Put that fragment on onCreate of the Activity with actions, So when by default when app launches it will show you your desired fragment.
Here is reference :
HomeFragment homeFragment = new HomeFragment().newInstance();
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, homeFragment)
.commit();
Full Code Here :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz);
loadFragment(new ProfileFragment());
BottomNavigationView navigation = findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
HomeFragment homeFragment = new HomeFragment().newInstance();
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, homeFragment)
.commit();
}

add this in your Mainactivity
navigation.setSelectedItemId(R.id.navigation_notifications); // Pass your menu id which you want to selected first

Set your mid tab as selected item
bottomNavigationView.setSelectedItemId(R.id.tab2);
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.tab1:
loadFragment(new ProfileFragment1());
return true;
case R.id.tab2:
loadFragment(new ProfileFragment2());
return true;
case R.id.tab3:
loadFragment(new ProfileFragment3());
return true;
}
return false;
}
};

Related

Why fragment is getting added to the back stack several times

I was trying to implement the bottom navigation with fragment inside an activity.
I have done that and it was successful.
To replace the fragment on click each navigation item, I use the following code.
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_notifications:
loadFragment(new NotificationsFragment());
return true;
case R.id.navigation_notes:
loadFragment(new NotesFragment());
return true;
case R.id.navigation_about:
loadFragment(new AboutFragment());
return true;
}
return false;
}
};
private void loadFragment(Fragment fragment) {
// load fragment
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_container, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
Now the problem is that when I click on a navigation in the bottom navigation bar multiple times, the fragment is also getting added to the back stack multiple times.
So when I click the back button the fragment is again loaded, not exiting or loading the previous fragment.
So, How can I prevent the fragment getting added to the back stack multiple times?
Remove
transaction.addToBackStack(null);
or add
transaction.disallowAddToBackStack();

Separate Back Stack for each tab in BottomNavigationView Android using Fragments

I'm implementing BottomNavigationView for navigation in an Android app. I am using Fragments to set the content for each tab.
I know how to set up one fragment for each tab and then switch fragments when a tab is clicked. But how can I have a separate back stack for each tab?
Here is the code to set up one fragment:
Fragment selectedFragment = ItemsFragment.newInstance();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.content, selectedFragment);
transaction.commit();
For an example, Fragment A and B would be under Tab 1 and Fragment C and D under Tab 2. When the app is started Fragment A is shown and Tab 1 is selected. Then Fragment A might be replaced with Fragment B. When Tab 2 is selected Fragment C should be displayed. If Tab 1 is then selected Fragment B should once again be displayed. At this point, it should be possible to use the back button to show Fragment A.
And Here is the code to set up next fragment in the same tab:
Fragment selectedFragment = ItemsFragment.newInstance();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.content, selectedFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(null);
ft.commit();
Finally, I found the solution, it was inspired by a previous answer on StackOverflow: Separate Back Stack for each tab in Android using Fragments
I only have replaced TabHost with BottomNavigationView and here is the code:
Main Activity
public class MainActivity extends AppCompatActivity {
private HashMap<String, Stack<Fragment>> mStacks;
public static final String TAB_HOME = "tab_home";
public static final String TAB_DASHBOARD = "tab_dashboard";
public static final String TAB_NOTIFICATIONS = "tab_notifications";
private String mCurrentTab;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
mStacks = new HashMap<String, Stack<Fragment>>();
mStacks.put(TAB_HOME, new Stack<Fragment>());
mStacks.put(TAB_DASHBOARD, new Stack<Fragment>());
mStacks.put(TAB_NOTIFICATIONS, new Stack<Fragment>());
navigation.setSelectedItemId(R.id.navigation_home);
}
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
selectedTab(TAB_HOME);
return true;
case R.id.navigation_dashboard:
selectedTab(TAB_DASHBOARD);
return true;
case R.id.navigation_notifications:
selectedTab(TAB_NOTIFICATIONS);
return true;
}
return false;
}
};
private void gotoFragment(Fragment selectedFragment)
{
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content, selectedFragment);
fragmentTransaction.commit();
}
private void selectedTab(String tabId)
{
mCurrentTab = tabId;
if(mStacks.get(tabId).size() == 0){
/*
* First time this tab is selected. So add first fragment of that tab.
* Dont need animation, so that argument is false.
* We are adding a new fragment which is not present in stack. So add to stack is true.
*/
if(tabId.equals(TAB_HOME)){
pushFragments(tabId, new HomeFragment(),true);
}else if(tabId.equals(TAB_DASHBOARD)){
pushFragments(tabId, new DashboardFragment(),true);
}else if(tabId.equals(TAB_NOTIFICATIONS)){
pushFragments(tabId, new NotificationsFragment(),true);
}
}else {
/*
* We are switching tabs, and target tab is already has atleast one fragment.
* No need of animation, no need of stack pushing. Just show the target fragment
*/
pushFragments(tabId, mStacks.get(tabId).lastElement(),false);
}
}
public void pushFragments(String tag, Fragment fragment, boolean shouldAdd){
if(shouldAdd)
mStacks.get(tag).push(fragment);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content, fragment);
ft.commit();
}
public void popFragments(){
/*
* Select the second last fragment in current tab's stack..
* which will be shown after the fragment transaction given below
*/
Fragment fragment = mStacks.get(mCurrentTab).elementAt(mStacks.get(mCurrentTab).size() - 2);
/*pop current fragment from stack.. */
mStacks.get(mCurrentTab).pop();
/* We have the target fragment in hand.. Just show it.. Show a standard navigation animation*/
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content, fragment);
ft.commit();
}
#Override
public void onBackPressed() {
if(mStacks.get(mCurrentTab).size() == 1){
// We are already showing first fragment of current tab, so when back pressed, we will finish this activity..
finish();
return;
}
/* Goto previous fragment in navigation stack of this tab */
popFragments();
}
}
Home fragment example
public class HomeFragment extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
Button gotoNextFragment = (Button) view.findViewById(R.id.gotoHome2);
gotoNextFragment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
((MainActivity)getActivity()).pushFragments(MainActivity.TAB_HOME, new Home2Fragment(),true);
}
});
return view;
}
}
This behavior is supported by the new Navigation Architecture Component (https://developer.android.com/topic/libraries/architecture/navigation/).
Essentially, one can use NavHostFragment, which is a fragment that controls its own back stack:
Each NavHostFragment has a NavController that defines valid navigation within the navigation host. This includes the navigation graph as well as navigation state such as current location and back stack that will be saved and restored along with the NavHostFragment itself.
https://developer.android.com/reference/androidx/navigation/fragment/NavHostFragment
Here is an example: https://github.com/deisold/navigation
Edit: Turns out Navigation Architecture Component doesn't support seperate back stacks anyway, as pointed out by the commenters. But as #r4jiv007 mentioned, they are working on it and has offered an "official hack" in the meantime: https://github.com/googlesamples/android-architecture-components/tree/master/NavigationAdvancedSample
It is worth noting that the behavior you describe goes against the Google guidelines. https://material.io/guidelines/components/bottom-navigation.html#bottom-navigation-behavior
Navigation through the bottom navigation bar should reset the task state.
In other words, having Fragment A and Fragment B "inside" Tab 1 is fine, but if the user opens Fragment B, clicks Tab 2, and then clicks Tab 1 again, they should see Fragment A.
Suppose you have 5(A, B, C, D, E) BottomNavigationView menu item, then in Activity create 5 FrameLayout(frmlytA, frmlytB, frmlytC, frmlytD, frmlytE) in parallel overlapping manner as the container for each of these menu items. When BottomNavigation Menu item A is pressed then hide all the other FrameLayouts(Visibility = GONE) and just show(Visibility = VISIBLE) the FrameLayout 'frmlytA' which will host the FragmentA and over this container do the further transactions like (FragmentA -> FragmentX -> FragmentY). And then If user clicks BottomNavigation Menu item B then just hide this(frmlytA) container and show 'frmlytB'. Then if user again presses the menu item A then show 'frmlytA' it should retain the earlier state. So, like this you can switch between the container FrameLayouts and can maintain the back stack of each container.
Instead of using replace method use add fragment,
Instead of this method
ft.replace(R.id.content, selectedFragment);
Use this
ft.add(R.id.content, selectedFragment);
Fragment selectedFragment = ItemsFragment.newInstance();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.(R.id.content, selectedFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(null);
ft.commit();

Create a tab indicator for a stack of fragments

I have an activity, and a bunch of fragments in it. The fragments are not transitioned by sliding, but by button click. I'm trying to build a tab indicator like the one in the bottom that shows which fragment the user is. I don't even know how it's called.
This is my main Activity where all the fragments belong, and with the actionbar menu the user navigates throught the fragments. In the activity it's switched straight to the first fragment out of 4 fragments (DetailsFragment)
public class CreateWorkoutActivity extends AppCompatActivity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_workout);
DetailsFragment fragment = new DetailsFragment();
getSupportFragmentManager().beginTransaction()
.replace(R.id.create_activity_frameLayout, fragment)
.addToBackStack(null)
.commit();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
FragmentManager fm = getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
fm.popBackStack();
}
return true;
}
return false;
}
image example
as i cannot see your code, I have this to offer https://guides.codepath.com/android/ViewPager-with-FragmentPagerAdapter ... refer this

How to remove the fragment when click on item again

Good Day,
I am facing some problem with fragments
I am displaying a fragment when user clicks on 'More', as a popup menu
but when I click the 'More' again, it would be like add one more fragment on the previous one
can someone tell me how to remove the fragment when I click on the 'More' again? Thank you!
the java code of bottom navigation menu
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView bottomNavigationView = (BottomNavigationView)
findViewById(R.id.bottom_navigation);
BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment fragment = null;
String title = "";
switch (item.getItemId()) {
case R.id.menu:
getFragmentManager().beginTransaction().replace(R.id.fragment_container, new MenuFragment()).addToBackStack(null).commit();
title = "MENU";
getSupportActionBar().setTitle(title);
break;
case R.id.promotion:
getFragmentManager().beginTransaction().replace(R.id.fragment_container, new PromotionFragment()).addToBackStack(null).commit();
title = "PROMOTION";
getSupportActionBar().setTitle(title);
break;
case R.id.order:
getFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrderFragment()).addToBackStack(null).commit();
title = "ORDER";
getSupportActionBar().setTitle(title);
break;
case R.id.location:
getFragmentManager().beginTransaction().replace(R.id.fragment_container, new LocationFragment()).addToBackStack(null).commit();
title = "LOCATION";
getSupportActionBar().setTitle(title);
break;
case R.id.more:
getFragmentManager().beginTransaction().add(R.id.fragment_container, new MoreFragment()).addToBackStack(null).commit();
break;
}
return true;
}});
}
}
Do not add your Popup Fragment to the backstack while transitioning to a new one. That is the first step you should do.
Next, rather than reopening the Popup on second "more" click, you should close it. Sounds like a better approach. But this would be probably better achieved by using Dialogs.
before calling transaction for 'more' add a tag with addToBackStack function(ex: moreFragment). check fragment manager and remove fragment like:
Fragment mFragment =getSupportFragmentManager().findFragmentByTag("moreFragment");
if(mFragment != null)
getSupportFragmentManager().beginTransaction().remove(mFragment);
But I think instead of removing old fragment just keep it and dont open new one if not null
To do this you have to keep track of fragment state. Lets assume a variable isFragmentOpen. In onClick you have to flip the variable and take your decision.
private boolean isFragmentOpen;
void onClick(View view) {
if (!isFragmentOpen) {
addFragment();
} else {
removeFragment();
}
// Flip the fragment state.
isFragmentOpen = !isFragmentOpen;
}
Please check how to add or delete fragment from official document Fragments
thanks for helping and now i already solve the problem^^
this is the code what i using
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
MoreFragment f = (MoreFragment) fm.findFragmentByTag("tag");
if(f == null) { // not added
f = new MoreFragment();
ft.add(R.id.fragment_container, f, "tag");
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
} else { // already added
ft.remove(f);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);
}
ft.commit();
break;

Why I need to press back button twice to dismiss fragment on first time?

I have Base Activity including NavigationView with 2 menu items. On start it loads Home fragment having background image inside it. Each loads specific fragment. When I select Terms & Conditions menu item, it loads T&C fragment & when I press back button it simply kills it.
However, when I select About Us menu item, it loads About Us fragment but I need to press BACK button twice to kill it. I need to know why does it happen?
Part of Code in AppBaseActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
fragmentManager = getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
HomeFragment homeFragment = new HomeFragment();
fragmentTransaction.add(R.id.body_container, homeFragment, "");
fragmentTransaction.commit();
}
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
navigationView.getMenu().findItem(item.getItemId()).setChecked(true);
switch (item.getItemId()) {
case R.id.nav_terms :
fragmentTransaction = fragmentManager.beginTransaction();
TCFragment tcFragment = new TCFragment();
fragmentTransaction.replace(R.id.body_container, tcFragment, "");
fragmentTransaction.commit();
break;
case R.id.nav_about_us :
fragmentTransaction = fragmentManager.beginTransaction();
AboutUsFragment aboutUsFragment = new AboutUsFragment();
fragmentTransaction.replace(R.id.body_container, aboutUsFragment, "");
fragmentTransaction.commit();
break;
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
All fragments simply have overridden onCreateView() by inflating respected xml only. No code is written in both fragments yet.
You can stop back hardware navigation if you want.
Simply using onBackPressed() without super.onBackPressed()
#Override
public void onBackPressed() {
}
#Override
public void onBackPressed() {
super.onBackPressed();
}

Categories

Resources