it-swarm.com.de

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

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

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 wird kompiliert, stürzt jedoch beim Start ab, wahrscheinlich, weil mein FragmentTransaction.add() falsch ist. Was ist der richtige Weg, um dies zu tun?

219
Tony Wong

Es stellt sich heraus, dass es mit diesem Code mehr als ein Problem gibt. Auf diese Weise kann ein Fragment nicht in derselben Java -Datei deklariert werden wie die Aktivität, jedoch 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.

Das zweite Problem ist, dass Sie beim Hinzufügen eines Fragments auf diese Weise einen Verweis auf die enthaltende Ansicht des Fragments übergeben müssen und diese Ansicht eine benutzerdefinierte ID haben muss. Wenn Sie die Standard-ID verwenden, stürzt die App ab. Hier ist 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;
        }
    }
}
185
Tony Wong

Folgendes habe ich mir ausgedacht, nachdem ich Tony Wongs Kommentar gelesen hatte :

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, schauen Sie sich die Kotlin-Erweiterungen von Google an, oder schreiben Sie einfach Ihre eigenen.

61
JJD
    public class Example1 extends FragmentActivity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
          DemoFragment fragmentDemo = (DemoFragment) 
          getSupportFragmentManager().findFragmentById(R.id.frame_container);
          //above part is to determine which fragment is in your frame_container
          setFragment(fragmentDemo);
                       (OR)
          setFragment(new TestFragment1());
        }

        // This could be moved into an abstract BaseActivity 
        // class for being re-used by several instances
        protected void setFragment(Fragment fragment) {
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = 
                fragmentManager.beginTransaction();
            fragmentTransaction.replace(Android.R.id.content, fragment);
            fragmentTransaction.commit();
        }
    }

Um ein Fragment zu einer Aktivität oder FramentActivity hinzuzufügen, ist ein Container erforderlich. Dieser Container sollte ein "Framelayout" sein, das in xml enthalten sein kann, oder Sie können den Standardcontainer für "Android.R.id.content" verwenden, um ein Fragment in Activity zu entfernen oder zu ersetzen.

main.xml

<RelativeLayout
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" >
 <!-- Framelayout to display Fragments -->
   <FrameLayout
        Android:id="@+id/frame_container"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent" />

    <ImageView
        Android:id="@+id/imagenext"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_alignParentBottom="true"
        Android:layout_alignParentRight="true"
        Android:layout_margin="16dp"
        Android:src="@drawable/next" />
</RelativeLayout>
31
anand krish

Nachdem ich alle Antworten gelesen hatte, kam ich auf elegante Weise auf:

public class MyActivity extends ActionBarActivity {

 Fragment fragment ;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    FragmentManager fm = getSupportFragmentManager();
    fragment = fm.findFragmentByTag("myFragmentTag");
    if (fragment == null) {
        FragmentTransaction ft = fm.beginTransaction();
        fragment =new MyFragment();
        ft.add(Android.R.id.content,fragment,"myFragmentTag");
        ft.commit();
    }

}

grundsätzlich müssen Sie kein frameLayout als Container Ihres Fragments hinzufügen, stattdessen können Sie das Fragment direkt in den Android -Root-View-Container einfügen

WICHTIG: Fragment nicht ersetzen wie die meisten hier gezeigten Vorgehensweisen, es sei denn, es macht Ihnen nichts aus, den Zustand der Fragmentvariableninstanz während des Prozesses onrecreation zu verlieren.

26
Xenione
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();
    }

}
5
user2212515

Für API Level 17 oder höher wird View.generateViewId() dieses Problem lösen. Die Dienstprogrammmethode stellt eine eindeutige ID bereit, die in der Erstellungszeit nicht verwendet wird.

4
Sfseyhan