1

I am trying to communicate within two fragments, the main and the child. however when i declare the interface in the child to pass values to the main fragment it works fine but when i want to pass from the main to the childfragment it doesn't work. by the way the fragment is in my MainActivity. Thanks for your help.

The error message is:

Caused by: java.lang.IllegalArgumentException: com.example.example.example.MainActivity must implement interface NotifyOnTutorialPageSelected

so is there a way to pass value without using static function directly? because what i have noticed that only the parent can implement the interface so what can i do it if i want to make it with interface? by the way it is for learning purposes.

CODE:

//MAin activity is something that calls only the mainfragment
public class MainActivity extends ActionBarActivity {

    FragmentManager fragmentManager;
    TutorialFragment tutorialFragment;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ActionBar actionBar = getSupportActionBar();
        actionBar.hide();


        fragmentManager = getSupportFragmentManager();    
        fragmentManager.findFragmentById(R.id.card_message_frag);
        tutorialFragment = (TutorialFragment) fragmentManager.findFragmentById(R.id.tutorial_frag);

    }
}

FIRST CLASS (called by MainActivity)

public class TutorialFragment extends Fragment implements ViewPager.OnPageChangeListener, OnTabSelected {

    FragmentManager fragmentManager;
    MultiTabFragment multiTabFragment;
    NotifyOnTutorialPageSelected notifyOnTutorialPageSelected;
    View tab ;
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final View view = inflater.inflate(R.layout.fragment_tutorial, container, false);
        fragmentManager = getChildFragmentManager();
        multiTabFragment = (MultiTabFragment) fragmentManager.findFragmentById(R.id.multi_tabs_frag);
        tab.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        //Log.e("clicked tab# ", "" + tabIndex);
                        onTabSelected.onTabSelected(tabIndex);
                    }
                });
        return view;
    }

    @Override
    public void onPageSelected(int position) {  
        notifyOnTutorialPageSelected.notifyOnTutorialPageSelected(position); // do something so can communicate with the child fragment
    }


    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        if (getActivity() instanceof NotifyOnTutorialPageSelected) {
            notifyOnTutorialPageSelected = (NotifyOnTutorialPageSelected) getActivity();
        } else if (getParentFragment() instanceof OnTabSelected) {
            notifyOnTutorialPageSelected = (NotifyOnTutorialPageSelected) getParentFragment();
        } else {
            throw new IllegalArgumentException(activity + " must implement interface " + NotifyOnTutorialPageSelected.class.getSimpleName());
        }

    }

    @Override
    public void onDetach() {
        notifyOnTutorialPageSelected = null;
        super.onDetach();
    }

    @Override
    public void onTabSelected(int index) {
        Log.e("INDEX_PASSED", "" + index);
        pager.setCurrentItem(index);
    }
}

SECOND CLASS (called by TutorialFragment)

public class MultiTabFragment extends Fragment implements NotifyOnTutorialPageSelected{
    private OnTabSelected onTabSelected;

    final int totalTabs = 4;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final View view = inflater.inflate(R.layout.multi_tab_fragment, container, false);
        //...
        return view;
    }


    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        if (getActivity() instanceof OnTabSelected) {
            onTabSelected = (OnTabSelected) getActivity();
        } else if (getParentFragment() instanceof OnTabSelected) {
            onTabSelected = (OnTabSelected) getParentFragment();
        } else {
            throw new IllegalArgumentException(activity + " must implement interface " + OnTabSelected.class.getSimpleName());
        }
    }

    @Override
    public void onDetach() {
        onTabSelected = null;
        super.onDetach();
    }

    @Override
    public void notifyOnTutorialPageSelected(int index) {
        deselectPreviousTab(index);
    }

SOLUTION:

Since nobody answered the question I will leave the answer right here if someone has similar difficulty. I solved this problem by implementing the interface to the MainActivity so the main activity would call the childclass and call the method:

//MAin activity is something that calls only the mainfragment
public class MainActivity extends ActionBarActivity implements NotifyOnTutorialPageSelected{

    FragmentManager fragmentManager;
    TutorialFragment tutorialFragment;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ActionBar actionBar = getSupportActionBar();
        actionBar.hide();


        fragmentManager = getSupportFragmentManager();    
        fragmentManager.findFragmentById(R.id.card_message_frag);
        tutorialFragment = (TutorialFragment) fragmentManager.findFragmentById(R.id.tutorial_frag);

    }

@Override
    public void notifyOnTutorialPageSelected(int index) {
        FragmentManager fragmentChildManager = tutorialFragment.getChildFragmentManager();
        MultiTabFragment multiTabFragment = (MultiTabFragment) fragmentChildManager.findFragmentById(R.id.multi_tabs_frag);
        multiTabFragment.deselectPreviousTab(index);
    }
}

it worked for me or at least for what i wanted, if someone has a different solution please tell me, Thanks.

kobbycoder
  • 682
  • 2
  • 10
  • 33
  • [Here](http://stackoverflow.com/a/23144683/4264819) already answered to your question! – Mirjalol Bahodirov Dec 12 '15 at 03:24
  • Thank you man! ill try it now – kobbycoder Dec 12 '15 at 03:28
  • notifyOnTutorialPageSelected = (NotifyOnTutorialPageSelected) getParentFragment(); if your notifyOnTutorialPageSelected implemented by child fragment how could you ask that thing from parent fragment. It should be some thing like notifyOnTutorialPageSelected = (NotifyOnTutorialPageSelected) getChildFragment(); – dex Dec 12 '15 at 03:29
  • @dex i just changed it and it is still saying that my main activity must implement that interface instead of child – kobbycoder Dec 12 '15 at 03:46

1 Answers1

1

You are throwing the exception yourself because your activity does not implement the NotifyOnTutorialPageSelected interface and your parent fragment must not implement the OnTabSelected interface.

The following code needs to be fixed to where one of the first two conditions is true. You have a potential mistake in your else if statement by the way since you are only checking if it is an instanceOf OnTabSelected but then cast the parent fragment as a NotifyOnTutorialPageSelected:

@Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        if (getActivity() instanceof NotifyOnTutorialPageSelected) {
            notifyOnTutorialPageSelected = (NotifyOnTutorialPageSelected) getActivity();
        } else if (getParentFragment() instanceof OnTabSelected) {
            notifyOnTutorialPageSelected = (NotifyOnTutorialPageSelected) getParentFragment();
        } else {
            throw new IllegalArgumentException(activity + " must implement interface " + NotifyOnTutorialPageSelected.class.getSimpleName());
        }

    }

Looking at your code I do not see how you have a child fragment since your tutorial fragment is not creating one.

Are you trying to have a single activity that displays two fragments that communicate?

If so take a look at the Android Documentation on how to do that using an interface.

EDIT:

You are likely going to find through this learning experience that there is a lot more wrong with your code. But to get you moving forward and away from your current error remove the onAttach method in your TutorialFragment fragment since it is wrong anyway. If you are going to have your Activity class implement the callback interfaces that is where it would go. Since you aren't doing it that way then there is no point in checking if your activity implements that particular interface.

Your MultiTabFragment.onAttach method only needs the following unless you are going to put the fragment directly into an activity sometimes:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    if (getParentFragment() instanceof OnTabSelected) {
        onTabSelected = (OnTabSelected) getParentFragment();
    } else {
        throw new IllegalArgumentException("Parent Fragment must implement interface " + OnTabSelected.class.getSimpleName());
    }
}

Finally since you are already keeping a reference to your MultiTabFragment in your TutorialFragment remove the NotifyOnTutorialPageSelected notifyOnTutorialPageSelected; and call to the fragment directly.

@Override
public void onPageSelected(int position) {  
    multiTabFragment.notifyOnTutorialPageSelected(position); // do something so can communicate with the child fragment
}
George Mulligan
  • 11,813
  • 6
  • 37
  • 50
  • it is but i am not showing all the code, main activity contains TutorialFragment and this contains childFragment – kobbycoder Dec 12 '15 at 03:40
  • error Caused by: java.lang.IllegalArgumentException: com.example.example.example.MainActivity@3d1d095 must implement interface NotifyOnTutorialPageSelected – kobbycoder Dec 12 '15 at 03:42
  • @kobbycoder You do not have your activity and fragments set up properly. As I mentioned you are throwing that exception yourself because your activity and parent fragment do not implement the interfaces you are expecting. – George Mulligan Dec 12 '15 at 03:51
  • then how the onTabSelected works? can you give me an example? – kobbycoder Dec 12 '15 at 03:52
  • The way your code is currently written makes little sense to me. Can you add to your question the code where you are adding your fragments? – George Mulligan Dec 12 '15 at 03:57
  • there it is... you can check now – kobbycoder Dec 12 '15 at 04:06
  • i didn't want to do it by calling directly to the fragment though and thanks for your clarification though. – kobbycoder Dec 12 '15 at 04:53
  • You don't have to call directly through the fragment. You just already kept a reference to it and that is the easiest way to do it given your current code. You could just keep a reference to it as an interface and it would still work. – George Mulligan Dec 12 '15 at 05:01