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();
}
Related
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();
}
}
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 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 have strange behaviour. Every time i replace the same type of fragment in Activity (using transaction), the new Fragment instance is added to Fragment List. The old instances remains active in Fragment Manager and after orientation change are visible on the screen (although not clickable).
My Activity Layout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
-->
<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->
<android.support.v4.widget.DrawerLayout
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.cubesoft.zenfolio.moments.app.activity.MainActivity" >
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
<fragment
android:id="#+id/navigation_drawer"
android:name="com.cubesoft.zenfolio.moments.app.fragment.NavigationDrawerFragment"
android:layout_width="#dimen/navigation_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
tools:layout="#layout/fragment_navigation_drawer" />
</android.support.v4.widget.DrawerLayout>
<fragment
android:id="#+id/fragmentConnectionStatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
class="com.cubesoft.zenfolio.fragment.ConnectionStatusFragment" />
My code that changes fragments:
#Override
public void onNavigationDrawerItemSelected(int position) {
mCurrentDrawerPosition = position;
// update the main content by replacing fragments
List<Fragment> fragmemts = getSupportFragmentManager().getFragments();
switch (position) {
case 0:{
if ( getMyApplication().getGroupModel().getUsersCount() > 0 ) {
final Fragment fragment = UserSelectionFragment.newInstance();
final FragmentManager fragmentManager = getSupportFragmentManager();
//fragmentManager.popBackStack();
final FragmentTransaction tr = fragmentManager
.beginTransaction();
tr.replace(R.id.container, fragment);
tr.addToBackStack(null);
tr.setCustomAnimations(R.anim.abc_fade_in, R.anim.abc_fade_out);
tr.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
tr.commit();
} else {
final Fragment fragment = MomentsFragment.newInstance(mUsername);
final FragmentManager fragmentManager = getSupportFragmentManager();
//fragmentManager.popBackStack();
final FragmentTransaction tr = fragmentManager
.beginTransaction();
tr.replace(R.id.container, fragment);
//tr.setCustomAnimations(R.anim.abc_fade_in, R.anim.abc_fade_out);
tr.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
tr.addToBackStack(null);
tr.commit();
}
break;
}
case 1: {
final Fragment fragment = DownloadFragment.newInstance();
final FragmentManager fragmentManager = getSupportFragmentManager();
//fragmentManager.popBackStack();
final FragmentTransaction tr = fragmentManager
.beginTransaction();
tr.replace(R.id.container, fragment);
tr.addToBackStack(null);
tr.commit();
break;
}
/*case 2:
fragment = UserSelectionFragment.newInstance();
break;*/
}
}
The UserSelectionFragment is displayed incorrectly after several orientation changes, old instances of UserSelectionFragment remains in Fragment List but their View objects are null.
What is wrong?
Try removing
tr.addToBackStack(null);
To me this adds your frgament to the backstack and thats the reason why they are kept in your fragment list. Their view are null because they have been destroyed before going to backgroud.
I've got a ListFragment with this:
public void fragmentSelection(Integer count) {
Fragment fr;
if (count == 0) {
fr = new Fragment1();
} else {
fr = new Fragment2();
}
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.content, fr, fr.getClass().getName());
fragmentTransaction.commit();
}
here I am trying to replace the fragment content with fr (depends on count value)..
the part from XML looks like this
<fragment
android:id="#+id/content"
android:name="com.test.app.DefaultContent"
android:layout_width="match_parent"
android:layout_height="match_parent">
</fragment>
Now when I want to replace fragment "content" with "fr" it do not replace it 1:1 - it adds fr down to the already current fragment (here DefaultContent) - so - why it does not replace it? What I have to do, that it replaces it and not puts the fr in addition below the current fragment
The View ID you pass to replace(), in your case R.id.content, has to be the ID of the Fragment's parent View, not the original Fragment itself.
That means you have to set android:id="#+id/content" to the Fragment's parent, like this:
<FragmentLayout
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:name="com.test.app.DefaultContent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FragmentLayout>
Or, if that does not work for you, set a new ID to the parent and use it for replace().