23

Let's consider a case where I have Fragment A and Fragment B.

B declares:

public interface MyInterface {
    public void onTrigger(int position);
}

A implements this interface.

When pushing Fragment B into stack, how should I pass reference of Fragment A for it in Bundle so A can get the onTrigger callback when needed.

My use case scenario is that A has ListView with items and B has ViewPager with items. Both contain same items and when user goes from B -> A before popping B it should trigger the callback for A to update it's ListView position to match with B pager position.

Thanks.

Niko
  • 8,093
  • 5
  • 49
  • 85

6 Answers6

33
Passing interface to Fragment

I think you are communicating between two Fragment

In order to do so, you can have a look into Communicating with Other Fragments

public class FragmentB extends Fragment{
    MyInterface mCallback;

    // Container Activity must implement this interface
    public interface MyInterface {
        public void onTrigger();
    }

    @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 {
            mCallback = (MyInterface ) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement MyInterface ");
        }
    }

    ...
}
Amit Gupta
  • 8,914
  • 1
  • 25
  • 33
6

For Kotlin 1.0.0-beta-3595

interface SomeCallback {}

class SomeFragment() : Fragment(){

    var callback : SomeCallback? = null //some might want late init, but I think this way is safer

    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        callback = activity as? SomeCallback //returns null if not type 'SomeCallback'

        return inflater!!.inflate(R.layout.frag_some_view, container, false);
    }
}
Krtko
  • 1,055
  • 18
  • 24
1

It is optimal for two fragments to only communicate through an activity. So you can define an interface in Fragment B that is implemented in the activity. Then in the activity, define in the interface method what you want to happen in fragment A.

In Fragment B,

MyInterface mCallback;
 public interface MyInterface {
        void onTrigger(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 {
            mCallback = (MyInterface) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement MyInterface");
        }
}

Method for determining if user goes from B to A

public void onChangeFragment(int position){
//other logic here
 mCallback.onTrigger(position);
}

In Activity,

public void onTrigger(int position) {
    //Find listview in fragment A
    listView.smoothScrollToPosition(position);
    }

Goodluck!

Yaya
  • 11
  • 3
0

Using @Amit's answer, and adapting to the OPs question, here is all the relevant code:

public class FragmentA extends BaseFragment implements MyInterface {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        // THIS IS JUST AN EXAMPLE OF WHERE YOU MIGHT CREATE FragmentB
        FragmentB myFragmentB = new FragmentB();        
    }


    void onTrigger(int position){
        // My Callback Happens Here!
    }
}

...

public class FragmentB extends BaseFragment {

    private MyInterface callback;

    public interface MyInterface {
        void onTrigger(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 {
            callback = (MyInterface ) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement MyInterface");
        }
    }
}
EdmundYeung99
  • 2,461
  • 4
  • 27
  • 43
0

I think you should use communication, as I've written below. This code comes from this Android Dev page of communication between Fragments:

HeadlinesFragment

public class HeadlinesFragment extends ListFragment {
OnHeadlineSelectedListener mCallback;

public void setOnHeadlineSelectedListener(Activity activity) {
    mCallback = activity;
}

// Container Activity must implement this interface
public interface OnHeadlineSelectedListener {
    public void onArticleSelected(int position);
}

// ...
}

MainActivity

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);
    }
}

public static class MainActivity extends Activity
    implements HeadlinesFragment.OnHeadlineSelectedListener {
...

public void onArticleSelected(int position) {
    // The user selected the headline of an article from the HeadlinesFragment
    // Do something here to display that article
}
ardiien
  • 767
  • 6
  • 26
  • Rather than linking, it would be more helpful to include the most relevant parts as a quoted block in your answer, and provide the link as a reference – MyStackRunnethOver Nov 20 '18 at 23:32
  • @MyStackRunnethOver I did so – ardiien Nov 20 '18 at 23:34
  • Ah, the code **is** the quote. Then perhaps your first line should be: "I think you should use communication, as I've written below. This code comes from [this Android Dev page on communication](https://developer.android.com/training/basics/fragments/communicating)" – MyStackRunnethOver Nov 20 '18 at 23:37
0

You may create call back interface by this way.

 var screenVisibility=activity as YourActivity
 screenVisibility.setScreenVisibility("which screen you want")