I am quite new in android, my intention is to pass this values to a fragment that it is my current fragment. But I want to update the fragment, I have this data in a different fragment.
When I execute this my bundle goes to the fragment. It doesn't change even I can do setText in my textView without the app stops.
private void passToScreen(String title, String artist, String album, Long duration) {
bundle.putString("songTitle",title);
bundle.putString("songArtist", artist);
bundle.putString("songAlbum", album);
bundle.putString("durationSong", duration.toString());
mActivity.getSupportFragmentManager()
.beginTransaction()
.detach(songScreen)
.commitNowAllowingStateLoss();
songScreen.setArguments(bundle);
mActivity.getSupportFragmentManager()
.beginTransaction()
.attach(songScreen)
.commitAllowingStateLoss();
})
What am I am doing wrong?
Thank you in advance.
If the fragment is already visible, then you can get the instance of that fragment using the FragmentManager:
MyFragment myFragment = (MyFragment) getSupportFragmentManager()
.findFragmentById(R.id.fragment_or_container_id);
myFragment.updateViews(bundle);
Then create the method in the fragment class to update the views:
public void updateViews(Bundle bundle) {
//update the views
}
You don't need to detach the fragment. Note that this will only work if the fragment is finished with the "commit" process. The commit() and commitAllowingStateLoss() functions work asynchronously, so if you call findFragmentById() immediately after commit(), it will return null.
Use interfaces to communicate between fragments
https://developer.android.com/training/basics/fragments/communicating.html
Related
I need to observe livedata changes in a Modelview to update a fragment (Adding the list to a recyclerview).
The implementation is working correctly but facing problems when switching between fragments.
If the implementation is on Fragment A when the user switches to Fragment B and then back to Fragment A a second livedata observer gets initiated. (Data in recyclerview gets duplicated) and so on...
I did some research on the Fragment Lifecycle and the need to remove the observer when moving between fragments (Either on Fragment Detach/Destroy) or before creating a new observer in the OnActivityCreated. But any of these worked.
I am observing the livedata as: mViewModel.getDetails().observe(getViewLifecycleOwner(), mObserver);
And tried to remove the observer as: mViewModel.getDetails().removeObservers(getViewLifecycleOwner()) or mViewModel.getDetails().removeObservers(this) or mViewModel.getDetails().removeObserver(mObserver) tried in OnViewCreated and onDestroyView and onDestory and onDetach
What is causing this and why removing the observer is not working?
FYI:
Here is the function i am using in the MainActivity to switch between fragments on navigation menu click
private boolean loadFragment(Fragment fragment) {
//switching fragment
if (fragment != null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, fragment)
.commit();
return true;
}
return false;
}
Try to set the value to null after
mViewModel.getDetails().removeObservers(getViewLifecycleOwner()).
mViewModel.getDetails().setValue(null)
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()
I'm having a hard time understanding how to replace fragments using the FragmentPagerAdapter. I have a class that extends FragmentPagerAdapter (android.support.v13.app.FragmentPagerAdapter) and my MainActivity implements ActionBar.TabListener, in the FragmentPageAdapter class I use the getItem() to setup my 3 fragments. so far so good.
One of these fragments is a ListView (pos #1), which I use a Listener to check on the onItemClick().
I want to replace the current ListView Fragment with another fragment so what I did is that inside the onItemClick() I perform the following code:
FragmentManager mFragmentManager = mActivity.getFragmentManager();
//new fragment to replace
Fragment mFragment = new TabPlaceFragment();
mFragmentManager.beginTransaction()
.replace(R.id.pager, mFragment)
.addToBackStack(null)
.commit();
What this is doing is that the fragment is replace with a blank fragment, I'm assuming is the pager, but the mFragment does not get replace. I tried giving an Id to the Current fragment and tried replacing it.
mFragmentManager.beginTransaction()
.replace(R.id.frament_old, mFragment)
.addToBackStack(null)
.commit();
But what this does is that it overlaps the new fragment on top of the old fragment
finally I tried getting the Id of the fragment to replace with the new, but this also gave me a blank fragment.
//this gives me the current fragment I want to replace
Fragment mCurrent = mFragmentManager.findFragmentByTag(MainHelper.getFragmentName(mViewPager.getId(), 1));
mFragmentManager.beginTransaction()
.replace(mCurrent.getId(), mFragment)
.addToBackStack(null)
.commit();
I'm sure I'm not implementing the method correctly but I cannot find a good example to follow the logic of my code. I thought of putting the fragment replacement in the MainActivity under getItem(), but don't know how to call it from within my onItemClick() Listener.
Any help is highly appreciated!!!
Thanks.
When my MainActivity is launched my ActionBar shows the app title. Once you navigate to a fragment through the nav drawer, the title is changed to match the fragment... however, once you navigate back using the back button, the title is left untouched and still has the title of the fragment. I am looking to change it back to the application Title.
I have tried to use the onResume() method in the MainActivity.java but it appears that does not get called once you leave a fragment.
#Override
public void onResume() {
super.onResume();
// Set title
getActionBar().setTitle("FuelR");
invalidateOptionsMenu();
}
Does anyone know what the best way would be to change the title back to the app_name ?
Thanks
Indeed destroying a Fragment within an Activity doesn't mean the activity will call onResume, first you have to notice that the Fragment lives within the Activity life context, and the Fragment do not alter it's life cycle, is just part of it, what you could do is within the fragment get a reference to the activity and set the title back to previous state, as shown below:
//In Fragment
#Override
public void onDestroyView() {
super.onDestroyView();
((Cast If Necessary)getActivity()).getActionBar().setTitle("Previous Title");
}
Or a more OOP approach would be, creating an interface that declares a method setTitlePreviousText, you implement that interface in your Activity class and from the fragment you could do this:
//In Fragment
#Override
public void onDestroyView() {
super.onDestroyView();
Activity act = getActivity()
if(act instanceof SetPreviousTextInterface){
//setTitlePreviousText will be called giving you the chance to just change it back...
((SetPreviousTextInterface)act).setTitlePreviousText();
}
}
This would be the interface file:
public interface SetPreviousTextInterface{
public void setTitlePreviousText();
}
Regards!
I need a function in my Activity, that sets fragment to my ViewGroup (FrameLayout in this case). Of course, I can use such construction:
public void setFragment(Fragment fragment){
FragmentManager fm=getFragmentManager();
//etc
}
But with this solution I need to create fragment somewhere else, not in my function. So, if class MyFragment extends Fragment, I need something like this:
setFragment(MyFragment);
Is it possible? Can I pass class as a parameter of function and then create instance of it
And if it's not - is it a bad idea to create fragment behind the function? Like
MyFragment my=new MyFragment();
setFragment(my);
If the two fragments are using the same layout then you can just do something like this
public void setFragment(){
Fragment newFragment;
if(displayFragOne){
newFragment = new MyFragment();
}else if(displayFragTwo){
newFragment = new OtherFragment();
}
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(r.id.the_id_of_layout,fragment).addToBackStack(null).commit();
}
the fragment paramater is passed in from where you initialized it usually in onCreate()
if you need the fragments to display at the same time then you need another FrameLayout to replace.
hopefully that answered your question, if not let me know
EDIT 2:
oh I see now you want to pass a class, sorry. As far as I know you cant do that, passing in an already initialized fragment would be a a better solution like I had before my first edit