Share information between fragments - android

I need to share information between fragments. I know that I can use sharedpreferences but I think that is not optimized.
This is the parent fragment code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view= inflater.inflate(R.layout.fragment_blank, container, false);
....
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.replace(R.id.eventos_pager, new BlankFragment2());
ft.commit();
....
return view;
}
This fragment call BlankFragment2 and BlankFragment1 need to sends information to BlankFragment2
I can share information to BlankFragment2 by the BlankFragment2's constructor. It is not allowed.

In Android you pass values to Fragments via bundles.
Using AndroidStudio File > New > Fragment > Fragment (Blank) will generate something like this.
public class MTFragment extends Fragment {
private String mParam1;
public static MTFragment newInstance(String param1) {
MTFragment fragment = new MTFragment();
Bundle args = new Bundle();
args.putString("value", param1);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString("value");
}
}
}
From your code:
MTFragment mFragment = MTFragment.newInstance("Hello");
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.replace(R.id.eventos_pager, mFragment);
ft.commit();

Related

Android how to send data from Activity to Fragment?

I want to pass data from my Activity to a Fragment. I have no idea how to do it. I've seen many solutions but no one of them did really work.
I just want to pass a simple String to the Fragment.
I have tried it this way:
public class PhotoActivty extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photo);
if (null == savedInstanceState) {
Bundle bundle = new Bundle();
String myMessage = "Stackoverflow is cool!";
bundle.putString("message", myMessage );
BasicFragment fragInfo = new BasicFragment();
fragInfo.setArguments(bundle);
android.app.FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.photo_frame, fragInfo);
transaction.commit();
}
}
}
What is the error there? I call it this way:
String myValue = this.getArguments().getString("message");
In the onCreateView in the Fragment
I usually use a static factory pattern:
public class MyFragment extends Fragment {
public static MyFragment newInstance(int index) {
MyFragment f = new MyFragment();
Bundle args = new Bundle();
args.putInt("index", index);
f.setArguments(args);
return f;
}
}
When you create the fragment in your Activity:
Fragment MyFragment = MyFragment.newInstance(5);
Alex Lockwood has a good rundown on why this is a preferred design pattern:
http://www.androiddesignpatterns.com/2012/05/using-newinstance-to-instantiate.html
Bundle bundle = new Bundle();
String myMessage = "Stackoverflow is cool!";
bundle.putString("message", myMessage );
Fragment fragInfo = new BasicFragment();
fragInfo.setArguments(bundle);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.photo_frame, fragInfo);
transaction.commit();
try this inside your if
from activity:
Bundle bundleObject = new Bundle();
bundleObject.putString("data", " Send From Activity");
/*set Fragmentclass Arguments*/
Fragment fragmentobject = new Fragment();
fragmentobject .setArguments(bundleObject );
From Fragment You receive this way:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String stringText = getArguments().getString("data");
return inflater.inflate(R.layout.fragment, container, false);
Not sure if this is the real cause of the problem, but you have to use getSupportFragmentManager() instead of getFragmentManager() inside AppCompatActivity. Also, classes such as Fragment and FragmentTransaction should come from support.v4 package.
Remove if (null == savedInstanceState) in your activity. If savedInstanceStatenull == null then BasicFragment will not replace your FrameLayout for R.id.photo_frame.

Passing data by using bundle between tablayout

I am using Bundle to passing data from my First TabFragment but it prompts out with the NullPointerException. Error is occur when getArguments() in list_fragments2 in second tab
MainActivity Fragment
list_fragment2 fragment = new list_fragment2();
Bundle b = new Bundle();
b.putString("test","text");
fragment.setArguments(b);
Toast.makeText(this, "" + b, Toast.LENGTH_SHORT).show();
SecondActivity Fragment
public class list_fragment2 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View h = inflater.inflate(R.layout.tab2, container, false);
TextView textView = (TextView) h.findViewById(R.id.textView);
Bundle bundle=getArguments();
//your string
if(bundle != null) {
String test = bundle.getString("test");
textView.setText(test);
}
return h;
}
}
Do you actually load your second fragment?
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
list_fragment2 fragment = new list_fragment2();
Bundle b = new Bundle();
b.putString("test","text");
fragment.setArguments(b);
fragmentTransaction.replace(placeholder, fragment);
fragmentTransaction.commit();
I think you can create your instance of list_fragment2 code within list_fragment2. Maybe your codes recreated list_fragment2 many times.
public static list_fragment2 createInstance() {
list_fragment2 fragment = new list_fragment2();
Bundle bundle = new Bundle();
bundle .putString("test","text");
fragment.setArguments(bundle);
return fragment;
}

Use single Fragment for multiple UI tasks?

I am using the Fragment master detail architecture
All Fragment Classes have the same logic
Is it possible to "detach" the Fragment from the layout and use just one Fragment class
So this code:
FragmentTransaction fragManager = getSupportFragmentManager().beginTransaction();
if("001".equalsIgnoreCase(id)){
arguments.putString(Fragment001.ARG_ITEM_ID, id);
Fragment001 fragment = new Fragment001();
fragment.setArguments(arguments); fragManager.replace(R.id.item_detail_container, fragment);
}
else if("002".equalsIgnoreCase(id)){
arguments.putString(Fragment002.ARG_ITEM_ID, id);
Fragment002 fragment = new Fragment002();
fragment.setArguments(arguments);
fragManager.replace(R.id.item_detail_container, fragment);
}
fragManager.commit();
Will turn into Something like:
FragmentTransaction fragManager = getSupportFragmentManager().beginTransaction();
GenericFragment fragment = new GenericFragment();
fragment.setUiId(id)
fragManager.replace(R.id.item_detail_container, fragment);
fragManager.commit();
List item
yes its possible, you can check and select which layout to use in onCreateView...
public static final String ARG_ITEM_ID1 = "fragment001";
public static final String ARG_ITEM_ID2 = "fragment002";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = null;
String id = "fragment001";
if(ARG_ITEM_ID1.equalsIgnoreCase(id)){
rootView = inflater.inflate(R.layout.fragment_1_layout, container, false);
}
else {
rootView = inflater.inflate(R.layout.fragment_2_layout, container, false);
}
return rootView;
}

How to Do Transaction of framents from one to another

I want to transact from one fragment to another... below given is my snippet...
I want transaction on button click...
public class Main extends Fragment {
// final View rootView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.main, container, false);
Button camera=(Button)rootView.findViewById(R.id.button1);
camera.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.layout.main, new CameraActivity());
ft.commit();
}
});
return rootView;
}
so please Assist me in solving this...
[1]<--->[2]<--->[3]<--->[4]<--->[5]
where []=fragments...
[1]- has buttons a,b,c,d,e
How to move from 1 to 3 OnClick of c ...
Here is the Camera Activity
public class CameraActivity extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.camera, container, false);
return rootView;
}
}
first of all this cant be activity
ft.replace(R.layout.main, new CameraActivity());
it has to be fragment
put something like this in your onclick listener in FirstFragment:
Bundle bundle = new Bundle();
bundle.putString("key", value); //if you want to pass parameter to second fragment
SecondFragment fragment = new SecondFragment();
fragment.setArguments(bundle);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment).addToBackStack(null);
ft.commit();
than in your SecondFragment onclick listener:
Bundle bundle = new Bundle();
bundle.putString("key", value); //if you want to pass parameter to second fragment
ThirdFragment fragment = new ThirdFragment();
fragment.setArguments(bundle);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment).addToBackStack(null);
ft.commit();
and so on ...
method addToBackStack(null) is providing you back as simple as that. You could also pass some tag in that method if you need it, but I think from question you want be needing it.
Also if you need to start Activity than dont use this method, use Intent instead.
hope it helps

Replacing a fragment with another fragment of the same class

I have a fragment (let's call it MyFragment) that inflates different layouts according to a parameter passed in the arguments.
All works well if MyFragment is started from a different fragment. But if MyFragment is active and I want to launch a new MyFragment with a different layout parameter, the fragmentManager does not create a new fragment at all.
data.setInt("Layout index",i);
fragmentTab0 = (Fragment) new MyFragment();
fragmentTab0.setArguments(data);
fragmentTransaction.replace(R.id.fragmentContent, fragmentTab0, "MY");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
How can I force convince the fragmentTransaction to launch the fragment again?
NOTE: The important point here is I need to inflate again a layout, which is different from the layout inflated before. The code looks like:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
switch( getArguments().getInt("Layout index") ) {
case 1:
rootView = inflater.inflate(R.layout.firstlayout, container, false);
break;
case 2:
rootView = inflater.inflate(R.layout.secondlayout, container, false);
break;
case 3:
rootView = inflater.inflate(R.layout.thirdlayout, container, false);
break;
default: break;
}
Bypass Solution
Explanation (hoover to see it)
Since the source code for fragmentTransaction.replace/add/remove is
not available I could not find what really happens. But it is
reasonable to think that at some point it compares the current class
name with the replacement class name and it exits if they are the
same.. Thanks to #devconsole for pointing out the source
code. I know now why this happens. The FragmentManager.removeFragment()
method does not reset the fragment state, it remains RESUMED, then the
method moveToState(CREATED) only initilizes a fragment if (f.mState <
newState) = if (RESUMED < CREATED) = false. Else, ergo, it just resumes the fragment.
So to solve this problem I created an almost empty fragment which only purpose is to replace itself with the target fragment.
public class JumpFragment {
public JumpFragment() {
}
#Override
public void onStart() {
Bundle data = getArguments();
int containerId = data.getString("containerID");
String tag = data.getString("tag");
//Class<?> c = data.get???("class");
//Fragment f = (Fragment) c.newInstance();
Fragment f = (Fragment) new MyFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
f.setArguments(data);
fragmentTransaction.replace(containerId, f, tag);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}
And I use it:
data.setInt("Layout index",i);
data.setInt("containerID",R.id.fragmentContent);
data.setString("tag","MY");
fragmentTab0 = (Fragment) new JumpFragment();
fragmentTab0.setArguments(data);
fragmentTransaction.replace(R.id.fragmentContent, fragmentTab0);
fragmentTransaction.commit();
Now no fragment is replaced by a same class fragment:
MyFragment -> JumpFragment -> MyFragment
I haven't figured out how to pass the class through the arguments bundle, to make it totally generic.
The following worked without problems for me. Notice that I used the Android Support Library.
activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<Button
android:id="#+id/button_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ONE" />
<Button
android:id="#+id/button_two"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/button_one"
android:text="TWO" />
<FrameLayout
android:id="#+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/button_one" >
</FrameLayout>
</RelativeLayout>
MainActivity.java:
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
Fragment fragment = DetailsFragment.newInstance("INITIAL");
transaction.add(R.id.main_container, fragment);
transaction.commit();
}
findViewById(R.id.button_one).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
update("Button 1 clicked");
}
});
findViewById(R.id.button_two).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
update("Button 2 clicked");
}
});
}
protected void update(String value) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
Fragment fragment = DetailsFragment.newInstance(value);
transaction.replace(R.id.main_container, fragment);
transaction.commit();
}
public static final class DetailsFragment extends Fragment {
public static DetailsFragment newInstance(String param) {
DetailsFragment fragment = new DetailsFragment();
Bundle args = new Bundle();
args.putString("param", param);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
TextView textView = new TextView(container.getContext());
textView.setText(getArguments().getString("param"));
return textView;
}
}
}
Did you try to first remove your fragment with remove(fragMgr.findFragmentByTag("MY"))and then add the new one ?
PS : I assume you don't keep any reference to this fragment.
If I understand you correctly: the fragment you want to replace what is currently being displayed and the user does something to cause it to re-display itself?
If this is correct then have done something similar this way:
public class MyFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
final View V = inflater.inflate(R.layout.myLayout, container, false);
// Call method that fills the layout with data
displayData(V);
// Put a listener here that checks for user input
Button redisplayButton = (Button) V.findViewById(R.id.my_button);
// if the button is clicked....
redisplayButton.setOnClickListener(new OnClickListener() {
public void onClick(View v){
//
// do some stuff
//
// ....then eventually...
displayData(V);
}
});
return V;
}
Later on you can have the displayData() method that defines what the fragment displays....
public void displayData(View V){
// Do something
return;
}
Hope this helps!

Categories

Resources