如何使用以编程方式创build的内容视图将片段添加到活动中
我想添加一个片段到一个活动,以编程方式实现其布局。 我查看了Fragment文档,但没有很多例子描述我需要什么。 这是我试图写的代码的types:
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()
不正确。 什么是正确的方法来做到这一点?
事实certificate,该代码有多个问题。 一个片段不能像这个活动那样在同一个java文件中被声明,而不能作为一个公共的内部类来声明。 框架期望片段的构造函数(没有参数)是公开的和可见的。 将片段作为内部类移动到Activity中,或者为片段创build一个新的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"; // ... }
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(); } }
要添加一个片段到一个活动或FramentActivity需要一个容器。 该容器应该是一个“
Framelayout
”,可以包含在XML中,或者你可以使用像“android.R.id.content
”这样的默认容器来删除或replaceActivity中的一个片段。
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>
阅读完所有答案我想出了一个优雅的方式:
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根视图容器
重要:除非你不介意在创build过程中丢失片段variables实例状态,否则不要使用replace片段作为这里显示的大部分方法。
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(); } }
对于API级别17或更高版本, View.generateViewId()将解决此问题。 该实用程序方法提供了一个不在构build时使用的唯一标识。