I have an Activity
with multiple Fragment
s. I want to show a DialogFragment
or open another Fragment
from one of the
Just follow the documentation:
Fragment
:
public class HeadlinesFragment extends Fragment {
// Container Activity must implement this interface
public interface OnHeadlineSelectedListener {
public void onArticleSelected(int position);
}
OnHeadlineSelectedListener mCallback;
// "Bind" to the Activity where this Fragment lives
public void setOnHeadlineSelectedListener(Activity activity) {
mCallback = (OnHeadlineSelectedListener) activity;
}
// ...
// This will send info to the Activity where the Fragment lives
private void someOtherFunctionOrListener(int position) {
mCallback.onArticleSelected(position); // pass info into Activity
}
}
Activity
:
public static class MainActivity extends Activity
implements HeadlinesFragment.OnHeadlineSelectedListener{
// ...
@Override
public void onAttachFragment(Fragment fragment) {
if (fragment instanceof HeadlinesFragment) {
HeadlinesFragment headlinesFragment = (HeadlinesFragment) fragment;
headlinesFragment.setOnHeadlineSelectedListener(this);
}
}
@Override
public void onArticleSelected(int position) {
// Call received from Fragment
}
}
Have you tried something like this (from the Fragment):
FragmentTransaction ft =
getActivity().getSupportFragmentManager().beginTransaction();
Fragment prev =
getActivity().getSupportFragmentManager().findFragmentByTag("some_name");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
DialogFragment dialogFragment = DialogFragmentClass.newInstance();
dialogFragment.show(ft, "some_name");
Let me know, cheers.
I think your second option is on the right track.
In your fragment, define the listener interface:
class MyFragment ...
{
public interface IMyFragmentListenerInterface
{
void DoSomething();
}
}
Have the activity implement the interface:
class MyActivity
{
class MyListener1 implements IMyFragmentListenerInterface { ... }
}
Pass the listener to the fragment. I like to do it in the Fragment's constructor, but that only works if you manage your fragments entirely by yourself. You can add a setListener
method to your fragment instead.
Create interface
public interface ListenFromActivity {
void doSomethingInFragment();
}
In Activity class keep refrence of ListenFromActivity
interface
public ListenFromActivity activityListener;
Make public method to set listener
public void setActivityListener(ListenFromActivity activityListener) {
this.activityListener = activityListener;
}
Add some trigger point in activity class, here I have used user interaction
@Override
public void onUserInteraction() {
super.onUserInteraction();
if (null != activityListener) {
activityListener.doSomethingInFragment();
}
}
Now in Fragment class
make your fragment implement interface class
public class SomeFragment extends Fragment implements ListenFromActivity
Android studio will prompt you to implement method of interface in fragment
void doSomethingInFragment()
{//Add your code here
}
Final part part listener instance to activity like this in fragment onCreate
method
((ListnerActivity) getActivity()).setActivityListener(SomeFragment.this);
DONE!!. now you can call fragment method from activity.
You will need to pass your data from Fragment X up to your FragmentActivity which will pass this data on to your Fragment Y. You do that by way of an interface defined in your fragment class and instantiate a callback that is defined in onAttach().
More information on how to do this here Communication With other Fragments
Quick example, consider Fragment A and Fragment B. Fragment A is a list fragment and whenever an item is selected it will change what is displayed in Fragment B. Simple enough, right?
At first, define Fragment A as such.
public class FragmentA extends ListFragment{
//onCreateView blah blah blah
}
And here's Fragment B
public class FragmentB extends Fragment{
//onCreateView blah blah blah
}
And here's my FragmentActivity that will govern them both
public class MainActivity extends FragmentActivity{
//onCreate
//set up your fragments
}
Presumably you have something like this already, now here's how you would change FragmentA(the list fragment that we need to get some data from).
public class FragmentA extends ListFragment implements onListItemSelectedListener, onItemClickListener{
OnListItemSelectedListener mListener;
//onCreateView blah blah blah
// Container Activity must implement this interface
public interface OnListItemSelectedListener {
public void onListItemSelected(int position);
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mListener = (OnListItemSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnListItemSelectedListener");
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
//Here's where you would get the position of the item selected in the list, and pass that position(and whatever other data you need to) up to the activity
//by way of the interface you defined in onAttach
mListener.onListItemSelected(position);
}
The most important consideration here is that your parent Activity implements this interface, or else you will get an exception. If implemented successfully, everytime an item in your list fragment is selected, your Activity will be notified of it's position. Obviously you could alter your interface with any number or type of parameters, in this example we're just passing in our integer position. Hope this clarifies a bit man, good luck.
To get a maximum in loose coupling you can use an event bus like OTTO from Square or EventBus from GreenRobot. Your fragments can fire events which are handled by your activity and vice versa. The cool thing about this is that the components (activities, fragments) no nothing about each other and you do not need to declare any interfaces or callbacks.
I use it in all my projects and it is robust and has low to no influence on the performance (in normal conditions).