Wie füge ich ein Fragment zu einer Aktivität mit einer programmatisch erstellten Inhaltsansicht hinzu?

Ich möchte ein Fragment zu einer Aktivität hinzufügen, die ihr Layout programmatisch implementiert. Ich habe mir die Fragment-Dokumentation angesehen, aber es gibt nicht viele Beispiele, die beschreiben, was ich brauche. Hier ist die Art von Code, die ich versucht habe zu schreiben:

public class DebugExampleTwo extends Activity {

    private ExampleTwoFragment mFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FrameLayout frame = new FrameLayout(this);
        if (savedInstanceState == null) {
            mFragment = new ExampleTwoFragment();
            FragmentTransaction ft = getFragmentManager().beginTransaction();
            ft.add(frame.getId(), mFragment).commit();
        }

        setContentView(frame);
    }
}

...

public class ExampleTwoFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, 
                             ViewGroup container, 
                             Bundle savedInstanceState) {
        Button button = new Button(getActivity());
        button.setText("Hello There");
        return button;
    }
}

Dieser Code kompiliert, stürzt aber beim Start ab, wahrscheinlich weil mein FragmentTransaction.add() falsch ist. Was ist der richtige Weg, dies zu tun?

Lösung

Es stellt sich heraus, dass es mehr als ein Problem mit diesem Code gibt. Ein Fragment kann nicht auf diese Weise deklariert werden, in derselben Java-Datei wie die Aktivität, aber nicht als öffentliche innere Klasse. Das Framework erwartet, dass der Konstruktor des Fragments (ohne Parameter) öffentlich und sichtbar ist. Das Verschieben des Fragments in die Activity als innere Klasse oder das Erstellen einer neuen Java-Datei für das Fragment behebt das Problem.

Das zweite Problem ist, dass Sie, wenn Sie ein Fragment auf diese Weise hinzufügen, einen Verweis auf die das Fragment enthaltende Ansicht übergeben müssen, und diese Ansicht muss eine benutzerdefinierte ID haben. Die Verwendung der Standard-ID führt zum Absturz der Anwendung. Hier's der aktualisierte Code:

public class DebugExampleTwo extends Activity {

    private static final int CONTENT_VIEW_ID = 10101010;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FrameLayout frame = new FrameLayout(this);
        frame.setId(CONTENT_VIEW_ID);
        setContentView(frame, new LayoutParams(
            LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

        if (savedInstanceState == null) {
            Fragment newFragment = new DebugExampleTwoFragment();
            FragmentTransaction ft = getFragmentManager().beginTransaction();
            ft.add(CONTENT_VIEW_ID, newFragment).commit();
        }
    }

    public static class DebugExampleTwoFragment extends Fragment {
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            EditText v = new EditText(getActivity());
            v.setText("Hello Fragment!");
            return v;
        }
    }
}
Kommentare (13)

Das habe ich mir nach der Lektüre von Tony Wong's Kommentar ausgedacht:

public class DebugExampleTwo extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addFragment(android.R.id.content,
                    new DebugExampleTwoFragment(),
                    DebugExampleTwoFragment.FRAGMENT_TAG);
    }

}

...

public abstract class BaseActivity extends Activity {

    protected void addFragment(@IdRes int containerViewId,
                               @NonNull Fragment fragment,
                               @NonNull String fragmentTag) {
        getSupportFragmentManager()
                .beginTransaction()
                .add(containerViewId, fragment, fragmentTag)
                .disallowAddToBackStack()
                .commit();
    }

    protected void replaceFragment(@IdRes int containerViewId,
                                   @NonNull Fragment fragment,
                                   @NonNull String fragmentTag,
                                   @Nullable String backStackStateName) {
        getSupportFragmentManager()
                .beginTransaction()
                .replace(containerViewId, fragment, fragmentTag)
                .addToBackStack(backStackStateName)
                .commit();
    }

}

...

public class DebugExampleTwoFragment extends Fragment {

    public static final String FRAGMENT_TAG = 
        BuildConfig.APPLICATION_ID + ".DEBUG_EXAMPLE_TWO_FRAGMENT_TAG";

    // ...

}

Kotlin

Wenn Sie Kotlin verwenden, werfen Sie einen Blick auf die Kotlin-Erweiterungen von Google oder schreiben Sie einfach Ihre eigenen.

Kommentare (1)
public abstract class SingleFragmentActivity extends Activity {

    public static final String FRAGMENT_TAG = "single";
    private Fragment fragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            fragment = onCreateFragment();
           getFragmentManager().beginTransaction()
                   .add(android.R.id.content, fragment, FRAGMENT_TAG)
                   .commit();
       } else {
           fragment = getFragmentManager().findFragmentByTag(FRAGMENT_TAG);
       }
   }

   public abstract Fragment onCreateFragment();

   public Fragment getFragment() {
       return fragment;
   }

}

verwenden.

public class ViewCatalogItemActivity extends SingleFragmentActivity {
    @Override
    public Fragment onCreateFragment() {
        return new FragmentWorkShops();
    }

}
Kommentare (0)