FragmentTransaction Replace only works once - android

Iam working on a page where i have three buttons working like tabs, and when clicking on one of them the behavior is expected to be that the FrameLayout (Fragment container) below should replace the fragment with the expected one.
in onCreate of the activity i have this method, so the container shows the first fragment, (this works fine):
ProductDetailInformacoesFragment infoFragment = new ProductDetailInformacoesFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.product_detail_fragment_container, infoFragment);
Then i have a switch statement that is called on the different listeners for the buttons, so the right fragment is shown:
public void switchFragment(int fragmentPos)
{
switch (fragmentPos){
case 0:
ProductDetailInformacoesFragment infoFragment = new ProductDetailInformacoesFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.product_detail_fragment_container, infoFragment);
ft.commit();
break;
case 1:
ProductDetailCaracteristicasFragment caracteristicasFragment = new ProductDetailCaracteristicasFragment();
FragmentTransaction ftt = getSupportFragmentManager().beginTransaction();
ftt.replace(R.id.product_detail_fragment_container, caracteristicasFragment);
ftt.commit();
break;
case 2:
ProductDetailAvaliacoesFragment avaliacoesFragment = new ProductDetailAvaliacoesFragment();
FragmentTransaction fttt = getSupportFragmentManager().beginTransaction();
fttt.replace(R.id.product_detail_fragment_container, avaliacoesFragment);
fttt.commit();
break;
default:
break;
}
}
XML:
<FrameLayout
android:id="#+id/product_detail_fragment_container"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/base_view"
android:background="#android:color/white"/>
The problem is when i click on one of the tabs, the fragment container become blank (white) and the desired fragment is not showed, no matter which one i click (even the one that is already shown). What am i doing wrong?? - i have tried setting ft.addToBackStack(null) didn't help.

.You should control if your frament is null before to instanciate and add it to the container. if your fragment is instanciated you should simply show it. if a button is clicked manage to show the desired fragment using trick mentioned above, and then hide the other fragments.
You should use ActionBar feature of android. and use Tab instead of your button. onTabSelected() onTabUnselected() to respectively manage operations on your Tab like attach or detach Fragments. everything is detailled in the android developper forum. Here is the URL http://developer.android.com/guide/topics/ui/actionbar.html so go to the section "Adding Navigation Tabs" for full explanation an example.
here is the overview of code for managing selection and unselection of your tabs using AndroidSupport
public void onTabSelected(Tab tab, FragmentTransaction fT) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
switch (tab.getPosition()) {
case your_tab_position:
if(your_fragment == null){
your_fragment = new Your_fragment();
ft.add(R.id.your_container, your_fragment, your_tag);
}
else{
ft.show(your_fragment);
}
break;
.
.
.
}
}
public void onTabUnselected(Tab tab, FragmentTransaction fT) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
switch (tab.getPosition()) {
case your_tab_position:
if(your_fragment != null){
ft.hide(your_fragment);
}
break;
.
.
.
}
}

Related

Fragments overlapping while using replace() [duplicate]

I have a fragment inside a group activity and I want to replace it with another fragment:
FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction();
SectionDescriptionFragment bdf = new SectionDescriptionFragment();
ft.replace(R.id.book_description_fragment, bdf);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
It works fine when it is done as a seperate project without using activity group, every thing works fine in log cat as control goes inside getview(), but no view is visible, not even any exception arises, I want the book detail fragment to be replaced by section detail fragment.
Xml of book detail fragment has id book_description_fragment and xml for section description fragment has id section_description_fragment.
The above code is in onClick method of an item, I want that when user taps on an item in horizontal scroll view, then the fragment changes.
Fragments that are hard coded in XML, cannot be replaced. If you need to replace a fragment with another, you should have added them dynamically, first of all.
Note: R.id.fragment_container is a layout or container of your choice in the activity you are bringing the fragment to.
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack if needed
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
Please see this Question
You can only replace a "dynamically added fragment".
So, if you want to add a dynamic fragment, see this example.
I've made a gist with THE perfect method to manage fragment replacement and lifecycle.
It only replace the current fragment by a new one, if it's not the same and if it's not in backstack (in this case it will pop it).
It contain several option as if you want the fragment to be saved in backstack.
=> See Gist here
Using this and a single Activity, you may want to add this to your activity:
#Override
public void onBackPressed() {
int fragments = getSupportFragmentManager().getBackStackEntryCount();
if (fragments == 1) {
finish();
return;
}
super.onBackPressed();
}
Use the below code in android.support.v4
FragmentTransaction ft1 = getFragmentManager().beginTransaction();
WebViewFragment w1 = new WebViewFragment();
w1.init(linkData.getLink());
ft1.addToBackStack(linkData.getName());
ft1.replace(R.id.listFragment, w1);
ft1.commit();
Use ViewPager. It's work for me.
final ViewPager viewPager = (ViewPager) getActivity().findViewById(R.id.vp_pager);
button = (Button)result.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewPager.setCurrentItem(1);
}
});
hope you are doing well.when I started work with Android Fragments then I was also having the same problem then I read about
1- How to switch fragment with other.
2- How to add fragment if Fragment container does not have any fragment.
then after some R&D, I created a function which helps me in many Projects till now and I am still using this simple function.
public void switchFragment(BaseFragment baseFragment) {
try {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
if (getSupportFragmentManager().findFragmentById(R.id.home_frame) == null) {
ft.add(R.id.home_frame, baseFragment);
} else {
ft.replace(R.id.home_frame, baseFragment);
}
ft.addToBackStack(null);
ft.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
enjoy your code time :)
you can use simple code its work for transaction
Fragment newFragment = new MainCategoryFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame_NavButtom, newFragment);
ft.commit();
You Can Use This code
((AppCompatActivity) getActivity()).getSupportFragmentManager().beginTransaction().replace(R.id.YourFrameLayout, new YourFragment()).commit();
or You Can This Use Code
YourFragment fragments=(YourFragment) getSupportFragmentManager().findFragmentById(R.id.FrameLayout);
if (fragments==null) {
getSupportFragmentManager().beginTransaction().replace(R.id.FrameLayout, new Fragment_News()).commit();
}
I change fragment dynamically in single line code
It is work in any SDK version and androidx
I use navigation as BottomNavigationView
BottomNavigationView btn_nav;
FragmentFirst fragmentFirst;
FragmentSecond fragmentSecond;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
fragmentFirst = new FragmentFirst();
fragmentSecond = new FragmentSecond ();
changeFragment(fragmentFirst); // at first time load the fragmentFirst
btn_nav = findViewById(R.id.bottomNav);
btn_nav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
switch(menuItem.getItemId()){
case R.id.menu_first_frag:
changeFragment(fragmentFirst); // change fragmentFirst
break;
case R.id.menu_second_frag:
changeFragment(fragmentSecond); // change fragmentSecond
break;
default:
Toast.makeText(SearchActivity.this, "Click on wrong bottom SORRY!", Toast.LENGTH_SHORT).show();
}
return true;
}
});
}
public void changeFragment(Fragment fragment) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_layout_changer, fragment).commit();
}
In kotlin you can do:
// instantiate the new fragment
val fragment: Fragment = ExampleFragment()
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.book_description_fragment, fragment)
transaction.addToBackStack("transaction_name")
// Commit the transaction
transaction.commit()
This will work if you're trying to change the fragment from another fragment.
Objects.requireNonNull(getActivity()).getSupportFragmentManager()
.beginTransaction()
.replace(R.id.home_fragment_container,new NewFragment())
NOTE As stated in the above answers, You need to have dynamic fragments.
You can use fragment-ktx
// If you are in fragmet
childFragmentManager.beginTransaction()
// or if you are in activiry
supportFragmentManager.beginTransaction()
// Create and commit a new transaction
supportFragmentManager.commit {
setReorderingAllowed(true)
// Replace whatever is in the fragment_container view with this fragment
replace<ExampleFragment>(R.id.fragment_container)
}
To replace a fragment with another one do this, Note that R.id.fragment comes from the id that you give to the first tag of the fragment in the XML.
barAudioPlaying.setOnClickListener(view -> {
getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment,new HomeFragment())
.commit();

Android Fragment appends when calling other fragment

Im currently working on a sample app that will be using fragments, but im having a little problem regarding changing the fragment.
My default layout for my fragment is fragmentOne (see code below).
<fragment
android:id="#+id/fplace"
android:layout_width="match_parent"
android:layout_height="498dp"
android:name="layout.FragmentOne"
tools:layout="#layout/fragment_fragment_one" />
and that's working correctly.
but when im changing the fragment it appends. the behavior must replace the fragment not append.
here is my code for the activity (see code below).
public void onClick(View view) {
Button button = (Button) view;
Fragment fragment = null;
switch (button.getId()) {
case R.id.f1:
fragment = new FragmentOne();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fplace, fragment);
ft.commit();
break;
case R.id.f2:
fragment = new FragmentTwo();
fm = getFragmentManager();
ft = fm.beginTransaction();
ft.replace(R.id.fplace, fragment);
ft.commit();
break;
}
}
and from the fragment one i am loading the data from the onCreateView() which is working correctly. the main problem is the fragment appends not replace.
(see photo below)
the red and yellow must be replaced by the blue colored fragment
As Mike said in comment
You cannot remove/replace Fragments that are declared in your layout.
So here is solution for you. Instead of fragment in xml use framelayout as container which will hold the fragment
use this instead of fragment in xml
<FrameLayout
android:id="#+id/fplace"
android:layout_width="match_parent"
android:layout_height="498dp"
/>
Hope this will help you.
declare a new fragmenttransaction in the second case dont use the fragment transaction that is used in the first case

Replace fragments in FrameLayout layout

I have tried every tutorial on the first google page about android fragments, but I can't get anything to work.
So I have one navigation bar activity, MainActivity.
Now I'd like to change fragments on a click in the drawer.
In my content_main (default fragment in the MainActivity activity), I have a framelayout that I wish to put the fragments in. I have the following fragments: fragment_main, fragment_one and fragment_two. And I wish to show these when I click on a button in the nav drawer.
The reason I want to use fragments is so that the nav drawer will stay on top.
Thanks in advance!
Edit: Here is the function I'll use to change fragments:
It's just to test, not finished.
public void setFragment() {
android.support.v4.app.FragmentTransaction transaction;
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, new LoginFragment());
transaction.commit();
}
I solved it!
Apparently, I had to use android.support.v4.app.Fragment; instead of android.app.Fragment;.
This is the code I got it to work with:
protected void setFragment(Fragment fragment) {
android.support.v4.app.FragmentTransaction t = getSupportFragmentManager().beginTransaction();
t.replace(R.id.fragment_container, fragment);
t.commit();
}
And to set it (from the nav bar onNavigationItemSelected(), you do this:
setFragment(new RoosterFragment());
I hope this helps others out with the same frustrating problem.
Accroding to your question,
This is FrameLayout
<FrameLayout
android:id="#+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/view"
android:layout_marginTop="#dimen/medium_margin"></FrameLayout>
Now , call displayview method onCreate() of your activity,
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//rest of your code here
displayView(0); // fragment at 0 position
}
displayView method, which have three fragements
public void displayView(int position) {
switch (position) {
case 0:
tvTitle.setText(getResources().getString(R.string.signin_tile));
showFragment(new LoginFragment(), position);
break;
case 1:
tvTitle.setText(getResources().getString(R.string.forgot_password_tile));
showFragment(new ForgotPasswordFragment(), position);
break;
case 2:
tvTitle.setText(getResources().getString(R.string.change_password_tile));
showFragment(new ChangePasswordFragment(), position);
break;
}
}
showFragment method called from displayView method,
public void showFragment(Fragment fragment, int position) {
FragmentTransaction mTransactiont = getSupportFragmentManager().beginTransaction();
mTransactiont.replace(R.id.main_container, fragment, fragment.getClass().getName());
mTransactiont.commit();
}
Did you try this? Click here
This link will Help you, to create fragment.
and this is what you want for navigation drawerClick here
Try this one. it is my newbie code easier to understand :)
FragmentTransaction transaction;
switch (id){
case R.id.button_fragment_one:
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout, new FragmentOne());
transaction.addToBackStack(null);
transaction.commit();
break;
case R.id.button_fragment_two:
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout, new FragmentTwo());
transaction.commit();
break;
default:
break;
}

how to switch from one fragment to another fragment android

Hi I have 5 fragments Now first time when I go to Activity of that fragments then default First fragment is called,then on first Fragment there is a button by clicking that button I go to the second fragment,similarly in Second fragment There is a button and clicking that button I go to the third fragment and so on.
Now My Question is that Current I am on Fifth fragment ,Now I want to go fifth fragment to second fragment,what should I do for this?
Can any one please tell me?
You can pop the fragment by name. While adding fragments to the back stack, just give them a name.
fragmentTransaction.addToBackStack("frag2");
Then in fragment5, pop the back stack using the name ie.. frag2 and include POP_BACK_STACK_INCLUSIVE
someButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fm = getActivity()
.getSupportFragmentManager();
fm.popBackStack ("frag2", FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
});
Here is the method to add and replace fragment.
public void addReplaceFragment(Fragment fragment, int addOrReplace) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
switch (addOrReplace) {
case addFragment:
transaction.add(R.id.frame_containerforsearchable, fragment);
transaction.commit();
break;
case replaceFragment:
transaction.replace(R.id.frame_containerforsearchable, fragment);
transaction.commit();
break;
default:
break;
}
}
call of fragment is..
addReplaceFragment(currencyFragmentWithSearch, replaceFragment);
replaceFragment integer variable
currencyFragmentWithSearch Fragment instance
You can always do this :)
getActivity().getSupportFragmentManager().replace(R.id.yourFrameLayout,new Fragment2(),"FRAG2");
OR
Fragment fragment = getActivity().getSupportFragmentManager().findFragmentByTag("FRAG2");
getActivity().getSupportFragmentManager().replace(R.id.yourFrameLayout,,"FRAG2");
Try this code:
Fragment fragment = new SecondFragmentName();
FragmentManager fm = getActivity().getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.commit();
just small correction to mudit_sen code. It is working, only if you add .beginTransaction. Thank you.
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.FrameLayoutId,new FragmentName()).commit();

Hiding/Showing fragments in Android

I have one FragmentActivity with Buttons in it and three Fragment classes. If Button 1 is clicked, I want to show FragmentOne and hide FragmentTwo,FragmentThree. and If Button2 is clicked, I want to show FragmentTwo and hide FragmentOne,FragmentThree and vice versa. My code didn't work.
private void fManager() {
FragmentManager manager = getSupportFragmentManager();
f1 = manager.findFragmentById(R.id.first);
f2 = manager.findFragmentById(R.id.second);
f2 = manager.findFragmentById(R.id.third);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
if (b1.isPressed()) {
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.hide(f2);
transaction.hide(f3);
transaction.show(f1);
transaction.commit();
}
break;
case R.id.button2:
if (b2.isPressed()) {
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.hide(f1);
transaction.hide(f3);
transaction.show(f2);
transaction.commit();
}
break;
case R.id.button3:
if (b3.isPressed()) {
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.hide(f1);
transaction.hide(f2);
transaction.show(f3);
transaction.commit();
}
break;
}
}
You need to commit your transaction:
transaction.commit();
Also note that show() and hide() will work only for fragments added to the container (like i.e. FrameLayout) so if you got your fragments defined directly in XML then you may not be able to do that the way you try. Also if you use containers, just do regular setVisibility() on them instead of dealing with fragments there - the effect will be exactly the same.
It is just an typo error or you are using the same var name to reference two objects?
f2 = manager.findFragmentById(R.id.second);
f2 = manager.findFragmentById(R.id.third);
If you want to have some more info about trasaction give a look on my blog, here.

Categories

Resources