Как добавить фрагмент в действие с программно созданным представлением содержимого
Я хочу добавить фрагмент в Activity, который программно реализует свой макет. Я просмотрел документацию Фрагмента, но примеров, описывающих то, что мне нужно, мало. Вот тип кода, который я пытался написать:
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()
неверен. Каков правильный способ сделать это?
Ответы
Ответ 1
Оказалось, что более чем одна проблема с этим кодом. Фрагмент не может быть объявлен таким образом внутри одного и того же файла java, как и активность, но не как открытый внутренний класс. Структура ожидает, что конструктор фрагмента (без параметров) будет общедоступным и видимым. Перемещение фрагмента в Activity как внутренний класс или создание нового java файла для исправлений фрагментов, которые.
Вторая проблема заключается в том, что когда вы добавляете фрагмент таким образом, вы должны передать ссылку на фрагмент, содержащий представление, и этот вид должен иметь собственный идентификатор. Использование 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;
}
}
}
Ответ 2
Вот что я придумал после прочтения комментария Тони Вонга:
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";
// ...
}
Ответ 3
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();
}
}
Чтобы добавить фрагмент в Activity или FramentActivity, требуется Контейнер. Этот контейнер должен быть "Framelayout
", который может быть включен в xml, иначе вы можете использовать контейнер по умолчанию для этого например, "android.R.id.content
" для удаления или замены фрагмента в Активность.
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>
Ответ 4
Прочитав все ответы, я придумал:
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();
}
}
в принципе вам не нужно добавлять frameLayout в качестве контейнера вашего фрагмента, вместо этого вы можете добавить фрагмент в корневой каталог Android.
ВАЖНО: не использовать фрагмент замены, как показано в приведенном здесь примере aproach, если вы не возражаете потерять состояние экземпляра экземпляра переменной во время процесса onrecreation.
Ответ 5
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;
}
}
использование
public class ViewCatalogItemActivity extends SingleFragmentActivity {
@Override
public Fragment onCreateFragment() {
return new FragmentWorkShops();
}
}
Ответ 6
Для API уровня 17 или выше View.generateViewId() решит эту проблему. Метод utility предоставляет уникальный идентификатор, который не используется во время сборки.