I am fairly new to android development, and I'm trying to make a small app that lists names with a few action buttons placed beside each name. My plan was to loop through the list of names, and add a fragment for each one, forming a list of them on the screen.
Right now I was trying to test out the following code. I want to add the fragment "fragTest", to "fragPlaceHolder" in the activity.
This is what my code looks like:
//Begin the transaction
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
//Replace the contents of the container with the new fragmentTest
for (int i = 0; i < listLength; i++){
ft.add(R.id.fragPlaceHolder, new fragmentTest());
}
//Complete the changes
ft.commit();
However when I do this, only one fragment ever seems to be added. And if it did work, how would I pass a name as an argument?
Use fragmentTransaction.AddToBackStack(null) in your code.
You can send data to fragment with intent:
Bundle bundle=new Bundle();
bundle.putString("message", "From Activity");
//set Fragmentclass Arguments
Fragmentclass fragobj=new Fragmentclass();
fragobj.setArguments(bundle);
Recieve data in fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String strtext=getArguments().getString("message");
return inflater.inflate(R.layout.fragment, container, false);
}
Related
I have a fragment which shows a list of buttons, each have their own id. When the user clicks the button, I am trying to replace the current fragment with another. Right after I replace the fragment, I a am adding arguments to the bundle. From what I can tell from debug mode, that part is working 100%. However, when we get to the new fragment, the "savedInstanceState" state will always be null.
I have read several posts on this however, I am confused because I am attempting to set the bundle and replace the fragment the same way I did when going from the activity to the first fragment and it is still not working.
MyActivity.java (this is working and all values are being set):
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyFirstFragment fragment = new MyFirstFragment();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame,fragment);
fragmentTransaction.commit();
Intent i = getIntent();
value = i.getExtras().getString("key");
Bundle bundle = new Bundle();
bundle.putString("key",value);
fragment.setArguments(bundle);
}
MyFirstFragment.java (also working):
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_first, container, false);
final String value = getArguments().getString("key");
myButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
String gid = Integer.toString(v.getId());
MySecondFragment secondfragment = new MySecondFragment();
Bundle secondFragmentBundle = new Bundle();
secondFragmentBundle.putString("key",value);
secondFragmentBundle.putString("id",id);
secondfragment.setArguments(secondFragmentBundle);
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame,secondfragment);
fragmentTransaction.commit();
}
});
MySecondFragment (getting null for savedInstanceState and all bundle agruments!):
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_second, container, false);
value = getArguments().getString("key");
id = getArguments().getString("id");
}
You cannot set arguments on a Fragment after it is attached to an Activity.
Your issue is caused by confusion about Fragment creation. What you provided in your question is not the correct way to send arguments to another Fragment type.
The de-facto standard way of passing arguments to a Fragment when it is created it to use a static factory method, generally called newInstance(). You should set the arguments this way, and should do so before committing the FragmentTransaction - however, you technically could do it right after committing the transaction with no ill effects. This is because when a Fragment is committed, it isn't immediately attached/created, rather, it is queued on the main thread.
Here is how you would do it:
Write a method in your Fragment class called new instance. Be sure to leave a public default (no arguments) constructor for the system to handle things in the background.
public MyFirstFragment extends Fragment {
public MyFirstFragment(){
//constructor - don't use this to create a new fragment directly
}
public static MyFirstFragment newInstance(String argument1, String argument2) {
// This is where you set the Fragment arguments:
MyFirstFragment instance = new MyFirstFragment();
Bundle arguments = new Bundle();
// add whatever arguments you need to the bundle
arguments.putString("ARGUMENT_1_KEY", argument1);
arguments.putString("ARGUMENT_2_KEY", argument2);
//Set the arguments on the new fragment instance
instance.setArguments(arguments);
return instance;
}
// recover the values in onCreate:
#Override
public void onCreate(Bundle savedInstanceState) {
// an easy way to check if this is a new instance is to null-check the saved state Bundle
if (savedInstanceState == null) {
String argument1 = getArguments().getString("ARGUMENT_1_KEY");
String argument2 = getArguments().getString("ARGUMENT_2_KEY");
} else {
// restore whatever you need from savedInstanceState bundle
}
}
Key point - the arguments are passed into the newInstance() method (these can be whatever you want, as long as the type is allowed). The newInstance() method enforces argument types and also prevents setting them after the fragment is already attached to an activity.
After this, in your Activity.onCreate() method:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String argument1 = "some information";
String argument2 = "other information";
MyFirstFragment fragment = MyFirstFragment.newInstance(argument1, argument2);
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame,fragment);
fragmentTransaction.commit();
}
This question already has answers here:
How to pass data between fragments
(13 answers)
Closed 6 years ago.
I am new to fragments. I added two edit texts in first fragment and I want to send that edittext data to second fragment.
I am using a bundle, but its printing null in second fragment.
Can anyone tell me how to send data to other fragment?
First fragment
nextt.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View _view) {
int viewId = _view.getId();
FragmentTransaction ft;
switch (viewId) {
case R.id.Button1:
FragmentManager fm = getFragmentManager();
ft = fm.beginTransaction();
SecondFrag secondFrag = new SecondFrag();
Bundle bundle = new Bundle();
bundle.putInt("deviceInst",viewId);
secondFrag.setArguments(bundle);
ft.replace(R.id.total_frame_content, secondFrag);
ft.addToBackStack(null);
ft.commit();
break;
}
}
});
In second fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.second_new, container, false);
String value = getArguments().getString("deviceInst");
System.out.println("TTTT"+ value);
In your first fragment you pass an int as an argument.
bundle.putInt("deviceInst",viewId);
And then, in your second fragment you try to get that argument by using
getArguments().getString("deviceInst")
which will fail, so to get the argument you pass you need to use getArguments().getInt("deviceInst")
For encapsulating the needed data, a good tip is to have a static newInstance() method in your fragments that requires data.
Here's a post about it.
https://plus.google.com/+AndroidDevelopers/posts/bCD7Zvd945d
You need to change like
int value = getArguments().getInt("deviceInst");
instead of
String value = getArguments().getString("deviceInst");
You will need to make the following changes in your code.
bundle.putString("deviceInst",editText.getText().toString());
Then in your second fragment you can get that argument by using
getArguments().getString("deviceInst")
Here editText is the instance of the edit text in the first fragment.
As you have passed int in the bundle, you need to use getInt() in your receiver fragment.
For example:
SecondFrag secondFrag = new SecondFrag();
Bundle bundle = new Bundle();
bundle.putInt("deviceInst",viewId);
secondFrag.setArguments(bundle);
getFragmentManager().beginTransaction().add(R.id.total_frame_content, secondFrag).commit();
In receiver fragment
String value = getArguments().getInt("deviceInst");
I'm really sorry for this stupid question but I've been reading various things but seems can't get through my thick skull. I'm really desperate here so please bear with me.
So I got one fragment full of text, say fragment_chapter_1.xml. One of the text need further explanation so I want to make it when the text (Copyright Act (Amendment) 1997) got clicked (it is not set clickable in xml layout), it will go to fragment_explain_law.xml.
The fragment_explain_law.xml have a TextView explainLaw, which will get setText (in ExplainLawFragment.java) to it's own explanation of the text clicked in fragment_chapter_1.xml. I use this way because if other text got clicked, it will reuse the same fragment_explain_law.xml but the explainLaw will set to different explanation.
Here's the code.
In Chapter1Fragment.java, it will view fragment_chapter_one.xml. law1 is id for Copyright Act (Amendment) 1997.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_chapter_1, container, false);
law1 = (TextView) rootView.findViewById(R.id.law1);
law1.setOnClickListener(this);
// Inflate the layout for this fragment
return rootView;
}
When law1 got clicked, fragment_explain_law.xml will be shown. For that, I make it by go to ExplainLawFragment.java (am I doing it right?).
#Override
public void onClick(View v) {
// when law1 till law11 clicked, go to ExplainLawFragment.java to view fragment_explain_law.xml
Fragment fragment = null;
String title = null;
switch (v.getId()) {
case R.id.law1:
// view explainLaw
fragment = new ExplainLawFragment();
title = "Copyright Act (Amendment) 1997";
break;
}
}
In ExplainLawFragment.java
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_explain_law, container, false);
explainLaw = (TextView) rootView.findViewById(R.id.explainLaw);
explainLaw.setText("blahblahblah");
// Inflate the layout for this fragment
return rootView;
}
Result: Nothing happen.
Logcat when I click law1: V/SettingsInterface: from settings cache , name = sound_effects_enabled , value = 1
Where did I go wrong? Please help.
You can call second fragment like this....
#Override
public void onClick(View v) {
// when law1 till law11 clicked, go to ExplainLawFragment.java to view fragment_explain_law.xml
Fragment fragment = null;
String title = null;
switch (v.getId()) {
case R.id.law1:
// view explainLaw
fragment = new ExplainLawFragment();
title = "Copyright Act (Amendment) 1997";
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
break;
}
Hope this will help you..
I'm making an android application with a navigation drawer.
I want this application to connect to the internet, and I need to put a label that contains informations about the connection into a fragment and some buttons to send information in another. I would like the label to update constantly, also if its fragment isn't shown.
My question is:
Is it possible to programmatically edit the elements of a fragment when it isn't shown?
as an answer to your comment, yes and this is how it works
Bundle bundle = new Bundle();
bundle.putString("key", "actualValue");
MyFragment fragment = new MyFragment();
fragment.setArguments(bundle);
// start your fragment
and then in your fragment onCreate or onCreateView
Bundle bundle = getArguments();
if(bundle !=null){
String actualData = bundle.getString("key");
TextView myTextView = (TextView)view.findViewById(R.id.myText);
myTextView.setText(actualData);
}
I want to be able to setText and getText of Views of individual Fragments. As it is now, when I setText of a Framgent's TextView it changes the text of that View in all Fragments.
I've been experimenting by moving things around, but here is my code as of this moment:
Fragment class
public class TestFragment extends Fragment{
View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.test_fragment, container, false);
TextView tv = (TextView) view.findViewById(R.id.huh);
//tv.setText("AAAAAAAAAAAAAAAAAAA");
return view;
}
public void setText(String asdf) {
TextView test = (TextView) view.findViewById(R.id.huh);
test.setText(asdf);
}
}
Activity Class
public class Manage extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.manage);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
TestFragment fragment = new TestFragment();
//fragment.setText("ASDF");
fragmentTransaction.add(R.id.test_fragment, fragment, "testtag");
fragmentTransaction.commit();
}
}
The framgent.xml is pretty plain; just a single TextView.
Fragments are added to stack with a parameter named tag. In your case you've added your fragment with "testtag".
fragmentTransaction.add(R.id.test_fragment, fragment, "testtag");
If you create multiple instances of same fragment and add them with unique tags, then you are able to get them with that unique tags. When you get a fragment then you can reach its content.
FragmentManager fm = this.getSupportFragmentManager();
Fragment testtagFragment = fm.findFragmentByTag("testtag");
View targetView = testtagFragment.getView().findViewById(R.id.anyViewInsideContentOfYourFragment);
Edit:
I want to be able to setText and getText of Views of individual
Fragments.
This question has 2 parts.
To setText while initializing you have to pass your initial
parameters to your fragment while creating its instance. I suggest
you to use a static newInstance method for this. See sample
here
To getText read my answer above. Note that, you can get the content of a fragment after its onCreateView method is executed. So If you try to call getView method of a fragment at your activities onCreate method (after you add the fragment), that will return null. You can get its content successfully under a click event to test that, and use get or set operations of any view on that fragment's content.