Red M
Red M

Reputation: 2789

Pass Fragment Class as a parameter

I'm not sure if this is doable, but I'm trying to pass a Fragment Class as a parameter so that I can have a centralized class with ONE method for multiple other classes.

Here is the method that I'm trying to write but I'm missing the "Fragment Class argument" in the method:

public void onStartFragment(??? ???, Fragment fragment, int containerViewId) {


    fragment = (???) getChildFragmentManager().
            findFragmentByTag(???.class.getName());

    if (fragment == null) {
        fragment = ???.newInstance();
    }
    FragmentTransaction childFragmentTransaction = getChildFragmentManager().beginTransaction();
    childFragmentTransaction.replace(containerViewId,
            fragment, ???.class.getName())
            .addToBackStack(null).commit();
}

My Goal is to have one method that can be used to start any fragment.

Upvotes: 1

Views: 3386

Answers (3)

Red M
Red M

Reputation: 2789

Continuing on @natario answer, I used the start fragment method in a separate class:

public class FragmentSeparateClass extends Fragment {

public void onStartFragment(Context context, FragmentManager fragmentManager, String className, int containerViewId) {

    Fragment fragment = fragmentManager.findFragmentByTag(className);

    if (fragment == null) {
        fragment = Fragment.instantiate(context, className);
    }
    fragmentManager.beginTransaction()
            .replace(containerViewId, fragment, className)
            .addToBackStack(className)
            .commit();
}

}

Then I used the method in the needed Fragment classes, for instance:

           fragmentSeperateCLass.onStartFragment(getContext(), getChildFragmentManager(), FirstChildFragment.class.getName(),
                    R.id.firstChildFragmentLayout);
        }

Upvotes: 1

natario
natario

Reputation: 25194

If you are planning to use the class name as a tag (and maybe a backstack entry name), just pass the class name, not the fragment.

Then use Fragment.instantiate(context, className) to have an instance of your class.

public void onStartFragment(String className, int containerViewId) {

    FragmentManager manager = getChildFragmentManager();
    Fragment fragment = manager.findFragmentByTag(className);
    if (fragment == null) {
        fragment = Fragment.instantiate(context, className);
        // fragment is a className instance now
    }

    manager.beginTransaction()
               .replace(containerViewId, fragment, className)
               .addToBackStack(className)
               .commit();
}

The method can be refined further depending on your desired behaviour, but you got the point. You can also pass a Class<? extends Fragment> if you wish.

Upvotes: 2

OneCricketeer
OneCricketeer

Reputation: 191743

Method overloading might help you here

public void onStartFragment(FragmentManger manager, Fragment fragment, String tag, int containerViewId) {

    // could check for tag here

    manager
        .beginTransaction()
        .replace(containerViewId, fragment, tag)
        .addToBackStack(null).commit();
}

public void onStartFragment(Fragment fragment, String tag, int containerViewId) {
    onStartFragment(
        getFragmentManager() // Or child, if you are in a Fragment already
        fragment, tag, containerViewId);
}

public void onStartFragment(Fragment fragment, int containerViewId) {
    onStartFragment(fragment, null, containerViewId);
}

Place whereever you need to call those methods,

MyFragment frag = new MyFragment();
onStartFragment(frag, frag.class.getName(), R.id.container); // for example

In other words, this should probably be handled externally of that method since I'm not sure you can reliably get ???.class.getName()

fragment = (???) getChildFragmentManager().
        findFragmentByTag(???.class.getName());

if (fragment == null) {
    fragment = ???.newInstance();
}

Upvotes: 1

Related Questions