fragmentTransaction.replace().commit() calls onCreate of parent Activity - java

I have a parent activity that stores several fragments, in the activity's onCreate I launch the first fragment
FatherFragment fatherFragment = new FatherFragment ();
RegisterActivity.this.getSupportFragmentManager (). BeginTransaction ().add (R.id.fragmentContainer, parentFragment, "RegisterParentFragment").commit ();
In the application the fragment is displayed correctly, but this fragment has a button that calls another fragment to replace it
MapsFragment mapsFragment = new MapsFragment();
Bundle bundle = new Bundle();
bundle.putString("idPersona", idPersona);
mapsFragment.setArguments (bundle);
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, mapsFragment, "mapaFragment")
.commit();
The problem resides in that, when making the fragment change (which if it is done) the onCreate method of the parent activity is launched again and shows me the first fragment over of the fragment that has just changed.
I have to assume that it is the view that is running again, but I would like to know if someone could help me find the solution to this problem.
I add that it is a series of steps between fragments and every time I switch, the same problem reappears.
Greetings and thanks for your time. Sorry for bad english.
Adding onClick method.
btnSgtPadre.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
guardarPersona(objPersona);
MapsFragment mapsFragment = new MapsFragment();
Bundle bundle = new Bundle();
bundle.putString("idPersona", idPersona);
mapsFragment.setArguments(bundle);
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, mapsFragment,"mapaFragment")
.commit();
}
});

Try this code :
in your Activity create method, which will add this fragment :
public void switchToSecondFragment(Object idPersona){
MapsFragment mapsFragment = new MapsFragment();
Bundle bundle = new Bundle();
bundle.putString("idPersona", idPersona);
mapsFragment.setArguments(bundle);
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, mapsFragment,"mapaFragment")
.commit();
}
And call it like this :
btnSgtPadre.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
guardarPersona(objPersona);
((<YourActivityName>) getActivity()).switchToSecondFragment(idPersona);
}
});
Most likely reason could be : App is restarting due to crash. Sometimes we don't get logs as well if app restarts.. try this and let me know.
Crash reason :
replace() method finds the ID inside your current fragment's layout, as you are passing "R.id.fragmentContainer", and your current fragment doesn't contain this "id", so you might me getting crash that this doesn't contain this id called "R.id.fragmentContainer". So you will have to add this fragment by writing method inside Activity itself.
If you want to confirm , add TryCatch :
try{
MapsFragment mapsFragment = new MapsFragment();
Bundle bundle = new Bundle();
bundle.putString("idPersona", idPersona);
mapsFragment.setArguments(bundle);
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, mapsFragment,"mapaFragment")
.commit();
}catch(Exception e){
e.printStackTrace();
}

Related

Flow of app within bottomsheet with fragments

I'm trying to continue the flow of app within bottomsheet.
Case : When a user clicks any brand suppose "Levis" then it should display the brand products i.e. another fragment(containing Products data) within the same bottomsheet only.
Problem: the another fragment(containing Products data) is opening in a seperate frame not in the existing bottomsheet.
My code on adapter holder click event:
holder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String id = ld.getBrand_id();
Bundle bundle = new Bundle();
bundle.putString("somekeyvalue", String.valueOf(id));
Fragment fragment = new ProductFragment();
fragment.setArguments(bundle);
FragmentManager fragmentManager = ((FragmentActivity) ct).getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frameLayout, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
I'm using Google material bottomsheet.
code to start bottomsheet:
BrandFragment bottomSheet = new BrandFragment();
bottomSheet.show(getChildFragmentManager(),
"ModalBottomSheet");
you are loading new ProductFragment() into R.id.frameLayout, which probably belongs to Activity. if you want to open new Fragment inside another one then define container, which belongs to this first Fragment. also use then getChildFragmentManager, not getSupportFragmentManager
btw. ensure that R.id.frameLayout is unique and declared ONLY inside "parent" Fragment, not in Activity

how to get from a fragment to an activity without disturbing fragment's reausability

This is now bugging me a lot.
I want to get to an activity from a Fragment without disturbing the reusability of the fragment. That mean I cant directly start an Intent from within the fragment to a the activity the fragment is currently attached to.
Here is the code under question
//This is the code inside the fragment
public void onStart() {
super.onStart();
View view = getView();
switch (position){
//case 1 is the case when the user clicks the ADD List Item from a ListFragment.
//Position is the position of ADD in the List Fragment.
case 1:{
Intent intent = new Intent(/*what exactly should I put here?*/ ,
/*this is where the reference to activity the fragment is attached to goes.
But we dont know what activty the fragment is attached to, as it is reusable
and may get attached to different activity at different times*/);
}
case 2:{
//this is the case when user decides to view the entered text in the array list.
TextView textView = (TextView)view.findViewById(R.id.display_name);
int size = workout.arrayList.size();
Object[] array = workout.arrayList.toArray();
for(int i=0;i<array.length;i++){
textView.setText((String)array[i] + "\n");
}
}
}
}
I feels like the data may be insufficient, although I am not sure what else to provide, sorry about that.
If more data is required, tell me.
Inside a Fragment we get the Context for an Intent using:
Intent intent = new Intent(getActivity(),AnyActivity.class);
OR
Intent intent = new Intent(getView.getContext(),AnyActivity.class);
The AnyActivity() can be any activity including the one currently having the Fragment.
You can open the same activity like this..
Intent intent = new Intent(getActivity(),SameActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
UPDATE To reuse the fragment for different values pass arguments to the fragment...during transaction..
Bundle bundle = new Bundle();
bundle.put("className", "SameActivity");
fragment.setArguments(bundle);
in fragment get the class name from bundle ... different class will pass different arguments as bundle..
In OtherActivity bundle would look like this..
Bundle bundle = new Bundle();
bundle.put("className", "OtherActivity");
fragment.setArguments(bundle);

How to change dynamically inflated textview from after proceeding an action on other fragment?

So, what my problem is that in one fragment(w/i a viewpager, I'll call this Fragment A) I click on this dynamically created button that adds a new fragment(I'll call this Fragment B) in a framelayout which allows me to use PayPal service. On PayPal Activity result, Fragment B communicates with the main Activity via a communicator(an interface class) to call Fragment A to change that text. But I'm getting a null pointer exeception crash.
To be specific:
what I did was that I made a global TextView variable that is initialized on click. I did this b/c I have a list of other things that are dynamically inflated and to avoid the TextView from being initialized with wrong layout I initialized it on click.
bidChange.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
eventListChangeKey = keyVal;
eventListChangeIdx = eventListIdx;
eventBiddingChangeIdx = finalI;
priceToChage = (TextView) biddersLayout.findViewById(R.id.single_list_bidder_bid_price);
Bundle bundle = new Bundle();
bundle.putInt("auctionID", auctionId);
bundle.putInt("dateID", dateId);
bundle.putInt("FromWhere", 2);
Fragment fragment = new Fragment_Home_ItemInfo_Bid();
fragment.setArguments(bundle);
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction()
.add(R.id.container_mainScreen, fragment, "itemInfo_bid")
.addToBackStack(null)
.setTransitionStyle(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.commit();
}
});
In the main activity
public void changeBidderPrice(String s) {
Fragment fragment = viewPagerAdapter.getItem(1);
((Fragment_List) fragment).changePrice(s);
}
is what I do
back in Fragment A
public void changePrice(String val) {
priceToChage.setText(val);
dataMap.get(eventListChangeKey).get(eventListChangeIdx).getBidList().get(eventBiddingChangeIdx).setPrice(val);
}
I've thought this over an over but I just can't figure this out. I've searched for similar cases in StackOverflow but I wasn't able to get a help.
Would the problem be the way I initialize that TextView? or is it the way I'm calling Fragment A from the main activity?
for fragments onViewCreated() is called after onCreateView() and ensures that the fragment's root view is non-null. Any view setup should happen here. E.g., view lookups, attaching listeners.
source : codepath
for activities onCreate()

"Could not find class android.transition.Transition" exception when pressing back button

I have one activity that hosts one fragment at a time, and swaps between two fragments. Fragment A starts Fragment B using a button, and Fragment B starts fragment A either using a button or the back button.
Everything works fine when going from Fragment A to B and from B to A using the custom buttons. The problem is when I use the back button to go from Fragment B to A (Fragment A adds the transaction to the back stack).
When pressing the back button while on Fragment B, I get several "Could not find class android.transition.Transition" exceptions and "Unable to resolve check-cast 1217 warnings, like 11 of each, which don't crash the program:
I have no idea what this means, or how this can be solved.
This is how Fragment A starts Fragment B:
mButtonNextFragment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fm = getActivity().getSupportFragmentManager();
Fragment fragment = FragmentTwo.newInstance(mCount);
fragment.setTargetFragment(FragmentOne.this, 0);
fm.beginTransaction()
.addToBackStack("transaction1")
.replace(R.id.layout_fragmentContainer, fragment)
.commit();
}
});
This is how Fragment B starts Fragment A:
mButtonPrevFragment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fm = getActivity().getSupportFragmentManager();
fm.beginTransaction()
.replace(R.id.layout_fragmentContainer, getTargetFragment())
.commit();
}
});
And this is how the host activity starts Fragment A:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment_container);
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.layout_fragmentContainer);
if (fragment == null) {
fragment = new FragmentOne();
fm.beginTransaction()
.add(R.id.layout_fragmentContainer, fragment)
.commit();
}
}
Anyone knows the cause of this problem?
Here is the complete error log: http://pastebin.com/CPtCUBYg
Kinda late, but I may have something. Not sure what's the cause of this problem, I`ll make some research later, but here in my Project happened the same error after I updated the android-support lib. Using an older version (that was inside HoloEverywhere library) worked normally.
Try using an older version of android-support to see if works better. Maybe something went deprecated in a recent version, but I'm not sure.

Replacing a fragment with another fragment inside activity group

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();

Categories