Fragment transaction add/replace not working from within a fragment - android

I have been breaking my head over this issue from a few days. Nothing seems to be working.
The following is the code where the fragment resides.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="#style/Theme.Breathe"
tools:context=".MainActivity">
<fragment
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#+id/mainFrag"
android:tag="fragment"
class="com.sneaky.example.HomeFrag"/>
</FrameLayout>
The following is the code from mainactivity where the first transaction happens. The below code executes and functions as expected.
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
Fragment fragment = new HomeFrag();
fragmentTransaction.add(R.id.mainFrag,fragment);
fragmentTransaction.commit();
The following is the code from HomeFrag that we added in the previous snippet. This code seems to be doing nothing. Clicking the card has no effect. CardView onClick seems to be working fine because Log.d and toasts execute onClick.
card.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
Fragment newFragment = new FragSec();
transaction.replace(R.id.mainFrag, newFragment);
transaction.addToBackStack(null);
transaction.commit();
}
});
Any help would be really appreciated. :D

If you already add HomeFrag by code, Try to change XML to this without declare <fragment/> inside
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="#style/Theme.Breathe"
android:id="#+id/mainFrag"
tools:context=".MainActivity"/>

Related

When navigating from one fragment to another, the second fragment overlaps

On the click of a button I want to navigate from one fragment to another. The problem is that when I press the button the second fragment overlaps the other.
I searched for some answers but it doesn't seem to word in my case. I tried adding a background color but it still overlaps.
So after I click the button the following thing happens:
Here are my codes:
I gave the first fragment an ID:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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=".ui.home.HomeFragment"
android:background="#FFF">
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="1dip"
app:layout_constraintBottom_toTopOf="parent"
android:background="#FFF"/>
The ID of the button is: nextFragment
The code inside the class of the first fragment is:
nextFragment = v.findViewById(R.id.nextFragment);
nextFragment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
Fragment fragment = new NotificationsFragment();
FragmentManager fragmentManager = getParentFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.fragment_container, fragment)
.addToBackStack(null)
.commit();
}
});
Hope i gave enough information, if not don't hesitate to ask for more! Thanks in advance.
The problem is that you are using fragment_container as the first fragment instead of the container for your first fragment.
In your MainActivity you have to load your first fragment inside that container. Not use it as a fragment.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState == null) {
Fragment firstFragment = new YourFirstFragment();
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.fragment_container, firstFragment);
transaction.commit();
}
}
After that, in your first fragment, when you will replace the fragment it will work great.
So the solution was simple.. I gave an Id to a framelayout inside the first fragment instead of to the root layout.
Now the next thing is that the tab on the bottom also has to change when the button is pressed.

Fragments overlapping on FrameLayout

I am trying to add multiple fragments to a FrameLayout. I need to add them one below another. But they are overlapping.
main_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
MainActivity.java
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
// Create instance of fragments
FragmentPrimaryList firstFrag = new FragmentPrimaryList();
FragmentSecondaryList secFrag = new FragmentSecondaryList();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// add fragment to the fragment container layout
fragmentTransaction.add(R.id.fragment_container,firstFrag);
fragmentTransaction.add(R.id.fragment_container,secFrag);
fragmentTransaction.commit();
}
}
They looks like this. How can I solve this?
Use the replace method instead of the add method.
The replace method hides the current fragment before adding new one, the add method simply adds the new fragment without disposing off the older fragment.
In order to retain the back stack, use the fragment transaction with backstack management.
I need to display both fragments at same time, one below another
You can try the following layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</LinearLayout>
Now add fragmments using:
fragmentTransaction.add(R.id.fragment_container1,firstFrag);
make sure you Fragment's layout_height = "wrap_content"
Add background to your fragments and make "android:clickable="true" to parent layout.
Do this way:
First fragment
FragmentPrimaryList firstFrag = new FragmentPrimaryList();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// add fragment to the fragment container layout
fragmentTransaction.add(R.id.fragment_container,firstFrag);
fragmentTransaction.commit();
second fragment
FragmentSecondaryList secFrag = new FragmentSecondaryList();
fragmentManager = getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_container,secFrag);
fragmentTransaction.commit();

Fragment to fragment to fragment get crash

I have a main activity , it contains lots of fragments.
Main activity layout looks like this:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.user.taiwandigestionsociety_v11.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF">
<include layout="#layout/toolbar"/>
//switch fragment over here
<FrameLayout
android:id="#+id/mainFrame"
android:layout_gravity="end"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</android.support.design.widget.AppBarLayout>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#android:color/transparent"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
and I click the drawer item it will change to first fragment:
#Override
public void onClick(View view) {
int id = view.getId();
if (id == R.id.activitiesContents) {
//change to first fragment successful
switchFragment(ActivityList.newInstance());
toolbar.setTitle(R.string.activitiesContents);
drawerLayout.closeDrawer(GravityCompat.START);
}
}
my switch fragment function:
public void switchFragment(Fragment fragment) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.mainFrame, fragment, null);
//transaction.addToBackStack(null);
transaction.commit();
}
then i click the button in first fragment, it changes to second fragment too:
//take me to second fragment succeed
switchFragment(ActivityHomePage.newInstance());
finally i click the button in second fragment, it crashed
//i want to switch to third fragment , just the same with previous
switchFragment(NewsInformation.newInstance());
the error log:
Why i got crash when i switch to third fragment? I completely have no clue.
I found the crash function function , because I set the class:
public class CommonSwitch extends Fragment {
//switch Fragment
public void switchFragment(Fragment fragment) {
FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.mainFrame, fragment, null);
//transaction.addToBackStack(null);
transaction.commit();
}
}
and I try to call it new CommonSwitch.switchFragment(goToFragment);
now I have set public void switchFragment every Fragment class.
Why when I set new CommonSwitch will cause crash ?
Your Activity state is Not Maintain.
On second layer use Activity instead of Fragment . Follow Android Standards.
According to standards Third Fragment should be Activity. otherwise you have to maintain MainActivity state.
Thanks

Back Button with strange behaviour on fragments

Here's my navigation:
HomeFragment -> LoginFragment -> CreateEventFragment
My HomeFragment is my first Fragment inside my MainActivity.
In my code, I'm replacing each one of them using the same view id( a FrameLayout inside my MainActivity's layout: R.id.container).
So every replace() is being called like this:
FragmentManager fragmentManager = mContext.getSupportFragmentManager();
fragmentManager.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.replace(containerId, nextFragment).addToBackStack(null).commit();
Except for LoginFragment to CreateEventFragment, because after the user logs in, he doesn't have to go back to LoginFragment so I don't call addToBackStack().
But something strange is happening:
When I'm on CreateEventFragment, after logging in successfully, and press the back button, my CreateEventFragment onDestroy() is not being called.
Debugging it I noticed that it isn't removed from the backStack, what am I doing wrong?
EDIT
Some code:
Common replace fragment method, inside BaseFragment, parent class of all three Fragments
public void replaceFragment(int containerId, Fragment nextFragment, boolean addToBackStack){
FragmentManager fragmentManager = mContext.getSupportFragmentManager();
if (addToBackStack)
fragmentManager.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.replace(containerId, nextFragment).addToBackStack(null).commit();
else
fragmentManager.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.replace(containerId, nextFragment).commit();
}
On HomeFragment:
BaseFragment nextFragment =
(PreferencesHandler.isLogged()) ?
CreateEventFragment.newInstance() :
LoginFragment.newInstance("create_event") ;
replaceFragment(R.id.main_fragment_container, nextFragment, true);
On LoginFragment:
public void goToNextFragment(){
Fragment nextFragment;
switch (mIntent){
case "create_event":
nextFragment = new CreateEventFragment();
break;
case "participate":
nextFragment = new ListsFragment();
break;
default:
nextFragment = new HomeFragment();
break;
}
replaceFragment(R.id.main_fragment_container, nextFragment, false);
}
My MainActivity's layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/toolbar_actionbar"
layout="#layout/toolbar_actionbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:layout_below="#+id/toolbar_actionbar"
tools:context=".MainActivity">
<FrameLayout
android:id="#+id/main_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar_actionbar"
/>
<fragment android:id="#+id/navigation_drawer"
android:layout_width="#dimen/navigation_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
android:name="Fragments.`NavigationDrawerFragment`"
tools:layout="#layout/fragment_navigation_drawer" />
</android.support.v4.widget.DrawerLayout>
</RelativeLayout>
EDIT 2
Noticed that pressing back button calls LoginFragment onDestroy, but not CreateFragment's. Also noticed that backStack has LoginFragment, guess it shouldn't, right?

Nothing shown If replace current fragment with another one

I have such layout:
frame_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/items"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
Next, in FragmentActivity I do:
setContentView(R.layout.fragment_layout);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
String tag = MyListFragment.class.getName();
MyListFragment fragment = (MyListFragment)
getSupportFragmentManager().findFragmentByTag(tag);
if (fragment == null) {
fragment = new MyListFragment();
ft.add(R.id.items, fragment, tag);
}
else {
ft.replace(R.id.items, fragment, tag);
}
ft.addToBackStack(null);
ft.commit();
When I call this code once, fragment shown perfectly! But, when it called twice I see no content!
After some investigation, I found that problem's caused by this:
setContentView(R.layout.fragment_layout);
E.g., when it is called once, fragment content is perfectly shown! But I need to call setContentView a lot of times to show another fragments.
Where's the mistake?
P.S. It's possible to make MyListFragment hardcoded into XML, but this does not fit to me, because I need to replace layout contents with other fragments.
As nobody answers, I found another solution: keep layout for every frame and show/hide them.
That's how I did it.... Main layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/container1"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
<FrameLayout
android:id="#+id/container2"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
That's how I show fragment2 (belongs to container2) in fragment activity:
findViewById(R.id.container1).setVisibility(View.GONE);
findViewById(R.id.container2).setVisibility(View.VISIBLE);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
String tag = MyFragment.class.getName();
Fragment fragment = (Fragment)getSupportFragmentManager().findFragmentByTag(tag);
if (fragment == null) {
fragment = new MyFragment();
ft.add(R.id.container2, fragment, tag);
}
ft.addToBackStack(null);
ft.commit();

Categories

Resources