I'm trying to create a application with bottom navigation view, But it looks like it is stacking up the fragments. Let me show you the picture to be clear.
[![Blank screen when back button is clicked again][3]][3]
Here is the code:
Home.xml
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/bottomfrag"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
/>
<com.google.android.material.bottomappbar.BottomAppBar
android:id="#+id/bottom_app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:contentInsetStart="0dp"
app:fabAlignmentMode="center">
<com.rawat.soccermatch.CustomBottomNav
android:id="#+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:itemRippleColor="#android:color/transparent"
app:labelVisibilityMode="labeled"
app:itemIconTint="#color/enable_disable"
app:itemTextColor="#color/enable_disable"
app:menu="#menu/bottom_nav_menu"
app:layout_behavior="#string/hide_bottom_view_on_scroll_behavior" />
</com.google.android.material.bottomappbar.BottomAppBar>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#FF9800"
android:contentDescription="#string/title_create"
android:src="#drawable/ic_plusn"
app:tint="#fff"
app:layout_anchor="#id/bottom_app_bar" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Home.java
bt = findViewById(R.id.bottomNavigationView);
loadFragment(new HomeFrag()); // at first home fragment will be loaded
bt.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment mfragment;
int item_id=item.getItemId();
if(item_id==R.id.navigation_home){
mfragment = new HomeFrag();
loadFragment(mfragment);
}
else if(item_id==R.id.navigation_feed){
mfragment = new Feed();
loadFragment(mfragment);
}
else if(item_id==R.id.navigation_create){
mfragment = new creatematch();
loadFragment(mfragment);
}
else if (item_id==R.id.navigation_following){
mfragment = new Following();
loadFragment(mfragment);
}
else {
mfragment = new Account();
loadFragment(mfragment);
}
return true;
}
});
ft = findViewById(R.id.fab);
ft.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ft.setBackgroundTintList(ColorStateList.valueOf(Color.GREEN));
ft.setRippleColor(Color.GREEN);
Fragment fragment = new creatematch();
bt.getMenu().findItem(R.id.navigation_create).setChecked(true);
loadFragment(fragment);
}
});
}
private void loadFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.bottomfrag, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
Should I post HomFrag Code too?
I have edited the question now the problem which I understand is when clicking back my Home Fragment is resuming from where it was left but the recylerview values are resetting and appends the new results with old. Also the ripple color is not changing from following to home.
Try to use this function instead of yours
public void loadFragment(Fragment fragment) {
try {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
manager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
ft.addToBackStack(null);
ft.replace(R.id.bottomfrag, fragment);
ft.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
you are adding that fragment to backstack so when you click back detach it, you need to make sure that your fragment is not added to backstack
Override onBackPressed() method. Inside it you can check what section is opened at the current moment and what you want to do in this case (nothing/close the app/navigate to another section).
in the bottom navigation activity you have to set default fragment is select which fragment you want for eg in common Home fragment always show as a default fragment so set homefragment as default.
set these code on create
bottomNavigationView.setSelectedItemId(R.id.nav_home);
checkon backpress
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() == 1) {
finish();
} else {
super.onBackPressed();
}
}
Related
Now I know this is a very simple question and was asked many times, but non of the solutions provided previously has worked for me.
I have an activity with a FrameLayout as follows:
<android.support.constraint.ConstraintLayout 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"
tools:context=".MainActivity">
<FrameLayout
android:id="#+id/replace_me"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</FrameLayout>
</android.support.constraint.ConstraintLayout>
And in my MainActivity class I have the following:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
replaceFragment(new ChooseLevelFragment(), false);
}
}
public void replaceFragment(Fragment fragment, boolean addToBackStack) {
FragmentTransaction replace = getSupportFragmentManager().beginTransaction().replace(R.id.replace_me, fragment);
if (addToBackStack) {
replace.addToBackStack(null);
}
replace.commit();
Log.d(TAG, "Fragment replaced!");
}
The first fragment is being shown correctly. However, when the user clicks on an item from the menu and logs in, the app should replace the current fragment with the new one
private void showAuthenticationDialog() {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
Fragment fragmentByTag = getSupportFragmentManager().findFragmentByTag(AuthenticationDialogFragment.TAG);
if (fragmentByTag != null) {
fragmentTransaction.remove(fragmentByTag);
}
fragmentTransaction.addToBackStack(null);
AuthenticationDialogFragment authenticationDialogFragment = AuthenticationDialogFragment.newInstance(() -> {
replaceFragment(new ParentControlPanelFragment(), true);
});
authenticationDialogFragment.show(fragmentTransaction, AuthenticationDialogFragment.TAG);
}
The new fragment is not being replaced even after the commit. I can see my log message but not the new fragment. I'm not quite sure where the problem is.
The problem was that I was trying to replace the fragment before I dismiss the dialog.
The correct approach is to dismiss the dialog first then try to replace the fragment.
I have a problem with my app. I have a bottom navigation view with 3 different fragments, although currently only the main this with things. The problem comes when I try to move from one of the two fragments of the left to the main, that is when the bottom navigation view is hidden. I attached the main code.
PD: I have all the libraries in 25.3.1 version (if useful).
Thank you for your attention.
activity_main.xml
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/containerr"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom">
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#0f6b96"
app:itemIconTint="#drawable/color_state_light"
app:itemTextColor="#drawable/color_state_light"
app:menu="#menu/menu_bottom_navigation_basic">
</android.support.design.widget.BottomNavigationView>
MainActivity.java
BottomNavigationView bottomNavigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(onNavigationItemSelectedListener);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transation = fragmentManager.beginTransaction();
transation.replace(R.id.container, new Home()).commit();
}
private BottomNavigationView.OnNavigationItemSelectedListener onNavigationItemSelectedListener = new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transation = fragmentManager.beginTransaction();
switch (item.getItemId()){
case R.id.home:
transation.replace(R.id.container, new Home()).commit();
return true;
case R.id.ofertas:
transation.replace(R.id.container, new Ofertas()).commit();
return true;
case R.id.contacto:
transation.replace(R.id.container, new Contacto()).commit();
return true;
}
return false;
}
};
I add you two images too.
Ofertas Fragment
Home Fragment
the problem is in fitSystemWindow == true , i had similar issue , after deleting it the problem has gone.
I'm using a navigation drawer to switch fragments, but elements from the first fragment stay present even on changing fragments.
The code of the main activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
...
Drawer result = new DrawerBuilder()
.withActivity(this)
.withToolbar(toolbar)
.addDrawerItems(
item1,
new DividerDrawerItem(),
item2,
new SecondaryDrawerItem().withName(R.string.drawer_item_settings)
)
.withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
#Override
public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
// do something with the clicked item :D
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
Fragment fragment = new Fragment();
switch (position)
{
case 0:
fragment = new HomeFragment();
Log.d("Switch", "Search");
break;
case 1:
break;
case 2:
fragment = new InventoryFragment();
Log.d("Switch", "Inventory");
break;
case 3:
fragment = new SettingsFragment();
Log.d("Switch", "Settings");
break;
}
transaction.replace(R.id.main_frame, fragment);
transaction.commit();
return false;
}
})
.build();
}
The following is the code for activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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:fitsSystemWindows="true"
android:background="?android:windowBackground"
tools:context="com.example.nihal.xchange.MainActivity">
...
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="#+id/main_frame">
<fragment
android:name="com.example.nihal.xchange.HomeFragment"
android:id="#+id/current_fragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>
Elements from Home Fragment remain present across fragments but this behavior is not exhibited by elements of other fragment.
How do I prevent this from happening?
Don't include the Home Fragment in the xml. Keep your container FrameLayout empty and add the initial fragment as soon as the activity starts. In your Activity's onCreate method, add the Home fragment dynamically in the beginning.
activity_main.xml -
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="#+id/main_frame">
<!-- Removed the fragment from here -->
</FrameLayout>
In the onCreate(), add it dynamically -
if (findViewById(R.id.main_frame) != null) {
if (savedInstanceState != null)
return;
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.main_frame, new HomeFragment());
transaction.commit();
}
I have a navigation drawer in an activity. The activity's layout has a relative layout for a fragment. The id of relativelayout is mainContent in which I load the fragment(call it fragA) in the onCreate() of the activity. I have this same fragment also in the navigation drawer along with other navigation items. It is loaded oncreate of activity and can also be loaded from navigation drawer.
On selecting the navigation items, I replace the fragment in the mainContent which is the relativelayout in the activity with replace(). In the navigation drawer, the 0th item is the "fragB"(the same as fragA but in nav drawer). Second is another fragment(fragC). When I select fragB "more than once" and then select fragA and press back button, fragB and fragC overlap.
And also I have to keep pressing back button to go to initial screen because every time I select an item from nav drawer, new fragments fragBs and fragCs are created. Not replaced. I replace them in mainContent(first relative layout) in the activity's layout. I'm using FrameLayout for the fragments.
This is the activity's layout in which I place fragments:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.prematixsofs.taxiapp.DateVehiclePicker">
<!-- The main content view -->
<RelativeLayout
android:id="#+id/mainContent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
layout="#layout/footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal|bottom"></include>
</RelativeLayout>
<!-- The navigation drawer -->
<RelativeLayout
android:id="#+id/drawerPane"
android:layout_width="230dp"
android:layout_height="match_parent"
android:layout_gravity="start">
<!-- Profile Box -->
<RelativeLayout
android:id="#+id/profileBox"
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="#ff02c7c4"
android:padding="8dp">
<ImageView
android:id="#+id/avatar"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginTop="15dp"
android:src="#drawable/user" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="42dp"
android:layout_centerVertical="true"
android:layout_marginLeft="15dp"
android:layout_toRightOf="#+id/avatar"
android:orientation="vertical">
<TextView
android:id="#+id/userName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:textColor="#fff"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="#+id/viewProfile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginTop="4dp"
android:text="View Profile"
android:textColor="#fff"
android:textSize="12sp" />
</LinearLayout>
</RelativeLayout>
<!-- List of Actions (pages) -->
<ListView
android:id="#+id/navList"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_below="#+id/profileBox"
android:background="#ffffffff"
android:choiceMode="singleChoice" />
<TextView
android:id="#+id/invisibleTextViewId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />
</RelativeLayout>
This is the Activity's code where I load the fragA:
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.mainContent, new DateTimePicker(),"tags").commit();
This is nav drawer onSelect:
private void selectItemFromDrawer(int position) {
Fragment fragment = null;
switch (position){
case 0: fragment = new DateTimePicker();
break;
case 1: fragment = new PreferencesFragment();
break;
case 2:
mDrawerLayout.closeDrawer(mDrawerPane);
AlertDialog.Builder alertDialog = new AlertDialog.Builder(DateVehiclePicker.this);
alertDialog.setTitle("Logout");
// Setting Dialog Message
alertDialog.setMessage("Do you want to Logout?");
alertDialog.setPositiveButton("YES", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
sessionManager.logoutUser();
}
});
alertDialog.setNegativeButton("NO", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);
dialog.cancel();
}
});
alertDialog.show();
}
if(fragment!=null)
{
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.addToBackStack(null).replace(R.id.mainContent, fragment);
fragmentTransaction.commit();
mDrawerLayout.closeDrawer(mDrawerPane);
}
This is where I set listener for nav drawer:
mDrawerList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItemFromDrawer(position);
}
});
I call the method selectItemFromDrawer(position);
You must handle BackStack for this you must clear all fragment which is on stack when you added or replace with main fragment
#Override
public void onBackPressed() {
Logg.e(TAG, getFragmentManager().getBackStackEntryCount());
try {
if (mNavigationDrawerFragment.isDrawerOpen())
{
mNavigationDrawerFragment.closeDrawer();
}
if (getFragmentManager().getBackStackEntryCount() > 1) {
getFragmentManager().popBackStack();
} else
{ Exit();
} catch (Exception e) {
e.printStackTrace();
}
}
Problem is you are creating new object for fragment transaction everytime you are trying to change fragment. Make it global in your code and use same instance everywhere.
Here is the code with switch case instead of if else
private void displayView(int position) {
Fragment fragment = null;
String title = getString(R.string.app_name);
switch (position) {
case 0:
fragment=new FragmentHome();
title="Home";
break;
case 1:
fragment=new FragmentAddress();
title="Update Address";
break;
case 2:
fragment=new FragmentHelpList();
title="My Helps";
break;
case 3:
fragment=new FragmentCompletedHelps();
title="History";
break;
case 4:
fragment=new FragmentSupport();
title="Account & Support";
break;
case 5:
fragment=new FragmentAbout();
title="About";
break;
case 6:
appSharedPreferences.setSession(false);
finish();
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment);
fragmentTransaction.commit();
// set the toolbar title
getSupportActionBar().setTitle(title);
}
Make the fragment variable global too
Try changing R.id.mainContent to R.id.container. I have similar setup but it is working fine with R.id.container.
fragmentManager.beginTransaction().replace(R.id.container,
new Registration_fragment()).commit();
and you have to replace FragA (not add) also initially during load.
fragmentTransaction.replace(R.id.mainContent, new DateTimePicker(),"tags").commit();
I'm having trouble with getting Fragments and the backstack to work.
I've got a layout with a FrameLayout for holding various fragments and another fragment:
<LinearLayout
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/filterableListContainer"
android:layout_weight="50">
</FrameLayout>
<fragment class="com.facetoe.remotempd.fragments.PlayerBarFragment"
android:id="#+id/playerBarFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
tools:layout="#layout/player_bar"/>
</LinearLayout>
When I start the Activity that uses this layout I add the fragment to the FrameLayout like so:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
if (findViewById(R.id.filterableListContainer) != null) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
// Create a new Fragment to be placed in the activity layout
ArtistListFragment listFragment = new ArtistListFragment();
// Add the fragment to the 'fragment_container' FrameLayout
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.filterableListContainer, listFragment);
ft.addToBackStack(null);
ft.commit();
} else {
Log.e(TAG, "Couldn't find filterableListFragment");
}
}
When the user clicks an item, I attempt to replace the fragment with this code:
ArtistAlbumsListFragment fragment = new ArtistAlbumsListFragment(getActivity(), albums);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.filterableListContainer, fragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
However when I press the back button I get returned to the home screen. Can anyone tell me where I'm going wrong?
Ok I fixed it. When I created the Activity in Intellij it created a subclass of ActionBarActivity. Removing ActionBarActivity and replacing it with Activity made the fragments transitions work as expected.
Dont add ft.addToBackStack(null) this statement.
ArtistAlbumsListFragment fragment = new ArtistAlbumsListFragment(getActivity(), albums);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.filterableListContainer, fragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();