我想添加一个片段,以编程方式实现其布局的活动。我查看了片段文档,但没有很多例子描述我需要什么。下面是我尝试编写的代码类型:
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()不正确。正确的做法是什么?
看完所有的答案后,我想出了一个优雅的方法:
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根视图容器
重要提示:不要像这里展示的大多数方法一样使用replace fragment,除非你不介意在onrecreation过程中丢失fragment变量实例状态。
看完所有的答案后,我想出了一个优雅的方法:
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根视图容器
重要提示:不要像这里展示的大多数方法一样使用replace fragment,除非你不介意在onrecreation过程中丢失fragment变量实例状态。
事实证明,该代码存在不止一个问题。片段不能以这种方式声明,在与活动相同的java文件中,但不能作为公共内部类声明。框架期望片段的构造函数(不带参数)是公共的和可见的。将片段作为一个内部类移动到Activity中,或者为片段创建一个新的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扩展或编写自己的扩展。
要在Kotlin中以编程方式将片段附加到一个活动,您可以查看以下代码:
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// create fragment instance
val fragment : FragmentName = FragmentName.newInstance()
// for passing data to fragment
val bundle = Bundle()
bundle.putString("data_to_be_passed", DATA)
fragment.arguments = bundle
// check is important to prevent activity from attaching the fragment if already its attached
if (savedInstanceState == null) {
supportFragmentManager
.beginTransaction()
.add(R.id.fragment_container, fragment, "fragment_name")
.commit()
}
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.MainActivity">
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
FragmentName.kt
class FragmentName : Fragment() {
companion object {
fun newInstance() = FragmentName()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// receiving the data passed from activity here
val data = arguments!!.getString("data_to_be_passed")
return view
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
}
}
如果您熟悉Kotlin中的扩展,那么您可以通过阅读本文来更好地理解这段代码。