Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding a listener between two fragments

I have two fragments, A and B let's say, where B contains a list. I would like to add a listener on Fragment B that notifies Fragment A of the chosen list item. I couldn't figure out how to initialize the listener in Fragment B since it is bad practice to pass arguments in fragment's constructors.

NOTE: Fragment B is contained inside Fragment A. i.e. I have a FrameLayout in Fragment A; and Fragment B covers that FrameLayout.

Any idea how I could do that?

like image 235
riadrifai Avatar asked Aug 25 '16 22:08

riadrifai


2 Answers

If you're saying that Fragment B is a child fragment of Fragment A (that is, you've added it to Fragment A using Fragment A's getChildFragmentManager()), then you can use the same approach that you use for Activity interfaces, but using getParentFragment() instead of getActivity().

For example:

Fragment B:

@Override
public void onAttach(Context context) {
    MyInterface myInterface = (MyInterface) getParentFragment();
}

Assuming that Fragment A implements MyInterface.

One convenience method we've used to avoid having to know whether a Fragment is hosted by another Fragment or an Activity is something like:

public static <T> getInterface(Class<T> interfaceClass, Fragment thisFragment) {
    final Fragment parent = thisFragment.getParentFragment();
    if (parent != null && interfaceClass.isAssignableFrom(parent)) {
        return interfaceClass.cast(parent);
    }

    final Activity activity = thisFragment.getActivity();
    if (activity != null && interfaceClass.isAssignableFrom(activity)) {
        return interfaceClass.cast(activity);
    }

    return null;
}

Then you can just use:

MyInterface myInterface = getInterface(MyInterface.class, this);

and it doesn't matter whether Fragment B is hosted as a child Fragment or in an Activity directly.

like image 100
Kevin Coppock Avatar answered Sep 20 '22 06:09

Kevin Coppock


A better approach for this situation, since what you want to do is communication between fragments, is to use an interface. You want to notify A when B has changed. This should be done through the parent activity. Here is the android documentation on the topic: https://developer.android.com/training/basics/fragments/communicating.html.

The gist of it is that you want to define an interface with a method called OnItemSelected (you can name it whatever you want). In B, you want a reference to this interface. When an item is selected, call your new OnItemSelected method. Implement this interface in the parent activity of the two fragments. In the implementation, you can put whatever code you want to modify A.

An example

CommunicationInterface

public interface CommunicationInterface {
    public void onItemSelected(int position);
}

FragmentB

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    CommunicationInterface myInterface = (CommunicationInterface) getActivity();
    // What ever else you want here
}

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    // Send the event to the host activity
    myInterface.onItemSelected(position);
}

MainActivity

public class MainActivity extends FragmentActivity implements CommunicationInterface {
    // What ever other code you have

    @Override
    public void onItemSelected(int position) {
        FragmentA fragA = (FragmentA)
        getSupportFragmentManager().findFragmentById(R.id.fragment_a);

        // Code to interact with Fragment A
    }
like image 23
JPal Avatar answered Sep 20 '22 06:09

JPal