Where should I invoke setarguments for a fragment in layout - java

I fail to understand that why is it only me facing such a trivial issue . I googled around and couldn't find much .
My case is simple . I have a layout with a fragment .
<fragment
android:id="#+id/tabs_fragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#id/header"
android:layout_above="#+id/footer"
class="com.uae.mopw.fragments.TabsFragment" />
I need to send arguments to this fragments , but I CAN'T SEEM TO FIGURE OUT HOW .
Had I been making a fragment in the code , I would have had a chance to invoke setarguments before the fragment gets attached to the activity .
However now I dont think I can control what happens when this fragment get attached to the activity because it happens during the initialization of the activity itself .
I try randomly overriding onFragmentAttached and setting the arguments there , however I still couldn't get through with it
I get a Fragment already active exception when I try the above .
Help ?
My activity Oncreate
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String moduleName = null;
if (Utils.getLanguage(this).equals("ar")) {
setContentView(R.layout.activity_application_for_work_to_work_ar);
isArabic=true;
moduleName=ModuleNames.DISTANCE_MEASUREMENT_SERVICE_AR;
} else {
setContentView(R.layout.activity_application_for_work_to_work);
isArabic=false;
moduleName=ModuleNames.DISTANCE_MEASUREMENT_SERVICE;
}
/*init header*/
new Header(this,HeaderTypes.HEADER_INTERNAL,moduleName);
/*take out bundle from intent*/
Bundle args = this.getIntent().getBundleExtra(ModuleNames.DISTANCE_MEASUREMENT_SERVICE);
/*Obtain fragment reference*/
fragment=(TabsFragment)getFragmentManager().findFragmentById(R.id.tabs_fragment);
fragment.setArguments(new Bundle());
}

Create a static method in your fragment for instanciating:
public static FooFragment newInstance(final String someValue) {
final FooFragment fooFragment = new FooFragment();
final Bundle bundle = new Bundle();
bundle.putString("key", someValue);
fooFragment.setArguments(bundle);
return fooFragment;
}
Use FragmentTransaction for adding or replacing the fragment:
transaction.replace(R.id.fragment_foo, FooFragment.newInstance("myValue"));
The you can access the data in your fragment by calling
getArguments().getString("key");

As far as I know you can' talk setArguments after the fragment is created. Thomas's answer works fine if you're adding fragments programatically but not if you're using an xml layout like you are. In your position I'd just get the fragment through a FragmentManager during your Activity's onCreate and then call a method on it to set the values you want. It's a different way of doing things, that's why I prefer to start my fragments programatically, not through xml, as the back stack is handled nicely for you too.

Related

Fragment doesn't update values from other fragment

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

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

Android set clickable text to go one fragment to another fragment

I need to do something like this. Suppose I have 2 fragments A and B.There is a text which can be clickable in fragment A and when user click this text , he can go to fragment B. This example helped me to do it but I think it does not work for fragment. So please tell me a way to solve this problem.
public class myClaimsFragment extends Fragment {
TextView requestNewClaim;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View newClaimRequest = inflater.inflate(R.layout.activity_my_claims, container, false);
SpannableString ss = new SpannableString("Request");
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View textView) {
Intent intent = new Intent(getActivity(),LoginActivity.class);
startActivity(intent);
}
};
ss.setSpan(clickableSpan , 0,ss.length() , Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
requestNewClaim =(TextView) newClaimRequest.findViewById(R.id.requestHere);
requestNewClaim.setText(ss.toString());
requestNewClaim.setMovementMethod(LinkMovementMethod.getInstance());
return newClaimRequest;
}
}
Layout XML
<LinearLayout
android:id="#+id/view2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/requestHere"
android:clickable="true"
android:textSize="20dp"
android:textStyle="bold"
android:textColor="#000000"
android:layout_marginLeft="20dp"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
</LinearLayout>
If LoginActivity is a fragment class then it would be okay if you use setOnClickListener on textview. But for fragment change you have to change Intent to fragmentTransaction,
Use something like,
textview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getFragmentManager().beginTransaction().replace(R.id.container, new LoginActivity() ).addToBackStack("").commit();
});
But, if you want to use SpannableString then do like this,
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View textView) {
getFragmentManager().beginTransaction().replace(R.id.container, new LoginActivity() ).addToBackStack("").commit();
}
};
Here, R.id.container is the fragment of your main activity layout in which new view will be replaced.
You can not call Fragment via Intent. You need to replace your current fragment with new one.
you have to replace your fragment A to B, use this code
FragmentManager fm = getActivity.getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment fragment = new FragmentB();
ft.replace(R.id.activity_main_content_fragment,fragment);
ft.commit();
In This code replace R.id.youframelayoutid, then it workable
If its code useful so please mark me my answer. :)
As an usual manner you should put a FrameLayout in your Activity's layout XML file. This FrameLayout acts like a placeholder for your Fragments. In other words, Fragment A can be pasted there, so is for Fragment B.
Okay, suppose you've added a FrameLayout in you activity's layout file. Pasting fragments on it and also replacing fragments should be done by the FragmentManager. Hence, you should grab a reference to a FragmentManger in your activity class. For getting this done ...
If you use Android Support Libraries, you should get a reference to FragmentManger by getSupportFragmentManager()
Otherwise, getFragmentManager()
In Android adding fragments and also replacing them are done in the form of a transaction. Thus you should inform the fragment manager that you would like to do a transaction. This could be done via:
FragmentTransaction transaction = fragmentManger.beginTransaction();
Now, you can apply all what you want on this transaction object. For instance, Adding a fragment could be done like this:
transaction.add(R.id.placeholder, new FragmentA() , "tag-frag-A");
For replacing ...
transaction.replace(R.id.placeholder, new FragmentB(), "tag-frag-B");
After you're done, you commit that transaction by calling
transaction.commit();
Notes:
FragmentManager acts like a container for your added fragments. You can search through your added fragments by their tag.
Device rotation does not remove added fragments in the FragmentManager. Thus in your onCreate method take care you've added any fragments only once.
You can add a Transaction to the back stack. This means that whenever user clicks on the Android back button this fragment will be removed from the state stack and also will be rolled back.

How pass fragment arguments while using a view pager with different fragments/layouts?

Objective: To use fragment arguments to pass along the string value from a TextView to a new fragments TextView, BUT while using a ViewPager with different layouts/fragments in the FragmentPagerAdapter.
Problem: The new fragment never receives the fragments arguments from the previous fragment.
My Set up: I have my Activity hosting the ViewPager and FragmentPagerAdapter. I have overridden FragmentPagerAdapters getItem(int position) method to create a new fragment instance depending on the current position of the ViewPager. Right now I only have two Fragments in my adapter, but will be adding more after getting over this obstacle. I am using the newInstance() technique to pass along the Fragment's arguments, but nothing is ever passed.
Pertinent Code:
My FragmentPagerAdapter code:
//this is a variable that I pass in as the newInstanct() methods parameter,
// I update this variable from my fragments constantly
public static String fragmentArgumentsValue = "";
mViewPager.setAdapter(new FragmentPagerAdapter(fm) {
#Override
public int getCount() {
return NUMBER_OF_VIEWS;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
Log.d(TAG, "---In getPosition(), position 0---");
return Frag1
.newInstance(fragmentArgumentsValue);
case 1:
Log.d(TAG, "---In getPosition(), position 1---");
return frag2
.newInstance(fragmentArgumentsValue);
default:
Log.d(TAG, "---In getPosition(), DEFAULT---");
return frag1
.newInstance(fragmentArgumentsValue);
}
}
});
One of the fragments newInstance() method:
public static Fragment newInstance(String fragmentArgumentsValue) {
Frag1 f = new Frag1();
Bundle bun = new Bundle();
bun.putString(KEY_FRAGMENT_ARGUMENTS_STRING, fragmentArgumentsValue);
f.setArguments(bun);
return f;
}
Getting the fragments arguments:
String argString = getArguments().getString(
KEY_FRAGMENT_ARGUMENTS_STRING);
if (argString.length() != 0) {
Log.d(TAG, "Trying to set the frag args to:" + argString);
mWorkingTextView.setText("" + argString);
} else {
Log.d(TAG, "Couldn't set frag args to: " + argString);
}
What I've Tried: I've tried giving the Activity that hosts the ViewPager and FragmentPagerAdapter a static variable that I constantly update in each one of my fragments, I include the static variable in the fragment.newInstance(staticVariableInActivity) method, but this doesn't seem to work.
I've also tried using the ViewPager callback viewPager.setOnPageChangeListener() I had overridden the onPageSelected(int pos) and tried to pass the fragment arguments there, nevertheless it didn't work... so please help me S.O.!!!
My thoughts: I do not have the different fragments and layouts in an ArrayList or any list for that matter, I just instantiate the Fragments via the newInstance() method depending on the positions of the FragementPagerAdapter, could this be a problem? Should I create a singleton list of the layouts/fragments? So I can change the values of the Fragments TextViews via the singleton list? (excuse me if that's a dumb or not possible thing to do).
Note: I am am saving away the TextViews values via public void onSaveInstanceState(Bundle outState) to handle screen rotations. Could this be a problem?
Alright so I this link will help in the communication between fragments: Communication with other Fragments .
You need to define a interface that the Activity will implement and the fragments will use to send data onward to the activity, and the activity will then find the fragment by tag doing something like this:
frag = (Fragment2) getSupportFragmentManager()
.findFragmentByTag(
"android:switcher:" + R.id.viewPager + ":2");
and then update the fragment by calling a public method implemented within the fragment.
The link provided will help greatly, it is from the Android Development website.
Adds the bundle inside your Adapter.
example in the constructor of the adapter :
public ViewPagerAdapter(Context context, FragmentManager fm) {
super(fm);
fragments.add(TileFragments.newInstance());
Bundle bundleFeatures = new Bundle();
bundleFeatures.putString(ContentName.FEATURES.toString(),ContentName.FEATURES.toString());
fragments.get(0).setArguments(bundleFeatures);
}

Create different fragment types by one function

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

Categories