Chcem pridať fragment do aktivity, ktorá programovo implementuje svoje rozloženie. Prešiel som si dokumentáciu k Fragmentu, ale nie je tam veľa príkladov, ktoré by opisovali to, čo potrebujem. Tu je typ kódu, ktorý som sa pokúsil napísať:
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;
}
}
Tento kód sa skompiluje, ale pri spustení spadne, pravdepodobne preto, že môj FragmentTransaction.add()
je nesprávny. Aký je správny spôsob, ako to urobiť?
Ukázalo sa, že s týmto kódom je viac ako jeden problém. Fragment nemôže byť deklarovaný týmto spôsobom, vo vnútri toho istého java súboru ako aktivita, ale nie ako verejná vnútorná trieda. Framework očakáva, že konštruktor fragmentu (bez parametrov) bude verejný a viditeľný. Presunutie fragmentu do aktivity ako vnútornej triedy alebo vytvorenie nového java súboru pre fragment to vyrieši.
Druhým problémom je, že keď pridávate fragment týmto spôsobom, musíte odovzdať odkaz na obsahujúci pohľad fragmentu a tento pohľad musí mať vlastné id. Použitie predvoleného id spôsobí pád aplikácie. Tu je aktualizovaný kód:
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;
}
}
}
Po prečítaní komentára Tonyho Wonga som prišiel na toto:
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";
// ...
}
Ak používate Kotlin, určite si pozrite, čo poskytujú Kotlin extensions od Google, alebo si jednoducho napíšte vlastné.
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;
}
}
použiť
public class ViewCatalogItemActivity extends SingleFragmentActivity {
@Override
public Fragment onCreateFragment() {
return new FragmentWorkShops();
}
}