Θέλω να προσθέσω ένα Fragment σε μια Δραστηριότητα που υλοποιεί τη διάταξή της προγραμματιστικά. Κοίταξα την τεκμηρίωση του Fragment αλλά δεν υπάρχουν πολλά παραδείγματα που να περιγράφουν αυτό που χρειάζομαι. Εδώ είναι ο τύπος του κώδικα που προσπάθησα να γράψω:
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;
}
}
Αυτός ο κώδικας μεταγλωττίζεται αλλά καταρρέει στην εκκίνηση, πιθανώς επειδή η FragmentTransaction.add()
είναι λανθασμένη. Ποιος είναι ο σωστός τρόπος για να γίνει αυτό;
Αποδεικνύεται ότι υπάρχουν περισσότερα από ένα προβλήματα με αυτόν τον κώδικα. Ένα θραύσμα δεν μπορεί να δηλωθεί με αυτόν τον τρόπο, μέσα στο ίδιο αρχείο java με τη δραστηριότητα, αλλά όχι ως δημόσια εσωτερική κλάση. Το πλαίσιο περιμένει ο κατασκευαστής του θραύσματος (χωρίς παραμέτρους) να είναι δημόσιος και ορατός. Η μετακίνηση του θραύσματος στη Δραστηριότητα ως εσωτερική κλάση ή η δημιουργία ενός νέου αρχείου java για το θραύσμα το διορθώνει αυτό.
Το δεύτερο ζήτημα είναι ότι όταν προσθέτετε ένα θραύσμα με αυτόν τον τρόπο, πρέπει να περάσετε μια αναφορά στην προβολή που περιέχει το θραύσμα και αυτή η προβολή πρέπει να έχει ένα προσαρμοσμένο id. Η χρήση του προεπιλεγμένου id θα προκαλέσει συντριβή της εφαρμογής. Εδώ είναι ο ενημερωμένος κώδικας:
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;
}
}
}
Εδώ είναι αυτό που σκέφτηκα μετά την ανάγνωση του σχολίου του Tony Wong:
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, φροντίστε να ρίξετε μια ματιά σε αυτά που παρέχουν οι Kotlin extensions της Google ή απλά γράψτε τις δικές σας.
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;
}
}
use
public class ViewCatalogItemActivity extends SingleFragmentActivity {
@Override
public Fragment onCreateFragment() {
return new FragmentWorkShops();
}
}