参考:
片段:https://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity
Fragment 使用(1):http://blog.csdn.net/u012005313/article/details/55215552
动态添加,替换和移除 fragment
fragment
设置 3
个按钮,分别用来添加,替换和移除 fragment
MainActivity.java
如下:
public class MainActivity extends AppCompatActivity{
private static final String TAG = "MainActivity";
private Button btnAdd;
private Button btnReplace;
private Button btnRemove;
private FrameLayout flContainer;
private FragmentManager fragmentManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
btnAdd = (Button) findViewById(R.id.btn_add);
btnReplace = (Button) findViewById(R.id.btn_replace);
btnRemove = (Button) findViewById(R.id.btn_remove);
flContainer = (FrameLayout) findViewById(R.id.fl_container);
fragmentManager = getSupportFragmentManager();
btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addFragment();
}
});
btnReplace.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
replaceFragment();
}
});
btnRemove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
removeFragment();
}
});
}
private void addFragment() {
OneFragment onefragment = new OneFragment();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fl_container, onefragment);
fragmentTransaction.commit();
btnAdd.setEnabled(false);
btnReplace.setEnabled(true);
}
private void replaceFragment() {
TwoFragment fragment = new TwoFragment();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fl_container, fragment, "twoFragment");
fragmentTransaction.commit();
btnReplace.setEnabled(false);
btnRemove.setEnabled(true);
}
private void removeFragment() {
TwoFragment fragment = (TwoFragment)fragmentManager.findFragmentByTag("twoFragment");
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.remove(fragment);
fragmentTransaction.commit();
btnRemove.setEnabled(false);
btnAdd.setEnabled(true);
}
}
activity_main.xml
如下:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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="com.zj.fragmentdemo.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_add"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="ADD" />
<Button
android:id="@+id/btn_replace"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:enabled="false"
android:text="REPLACE" />
<Button
android:id="@+id/btn_remove"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:enabled="false"
android:text="REMOVE" />
</LinearLayout>
<FrameLayout
android:id="@+id/fl_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@color/colorAccent" />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
在 activity
中进行 fragment
的添加,替换和移除,使用 FragmentTransaction
FragmentTransaction
通过 FragmentManager
获得:
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Note 1:每次进行 fragment
操作,必须重新获取 FragmentTransaction
Note 2:每次进行 fragment
更改后,必须调用 commit
方法
添加
add
方法有多种重载,介绍其中两种:
/**
* Calls {@link #add(int, Fragment, String)} with a null tag.
*/
public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment);
/**
* Add a fragment to the activity state. This fragment may optionally
* also have its view (if {@link Fragment#onCreateView Fragment.onCreateView}
* returns non-null) into a container view of the activity.
*
* @param containerViewId Optional identifier of the container this fragment is
* to be placed in. If 0, it will not be placed in a container.
* @param fragment The fragment to be added. This fragment must not already
* be added to the activity.
* @param tag Optional tag name for the fragment, to later retrieve the
* fragment with {@link FragmentManager#findFragmentByTag(String)
* FragmentManager.findFragmentByTag(String)}.
*
* @return Returns the same FragmentTransaction instance.
*/
public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment,
@Nullable String tag);
第一个参数 containerViewId
指定 activity
中放置 fragment
的位置
第二个参数 fragment
指定要添加的片段
第三个参数 tag
表示该 fragment
的标识符,之后可以通过函数 findFragmentByTag
找回该 fragment
替换
replace
函数有 2
个重载方法:
/**
* Calls {@link #replace(int, Fragment, String)} with a null tag.
*/
public abstract FragmentTransaction replace(@IdRes int containerViewId, Fragment fragment);
/**
* Replace an existing fragment that was added to a container. This is
* essentially the same as calling {@link #remove(Fragment)} for all
* currently added fragments that were added with the same containerViewId
* and then {@link #add(int, Fragment, String)} with the same arguments
* given here.
*
* @param containerViewId Identifier of the container whose fragment(s) are
* to be replaced.
* @param fragment The new fragment to place in the container.
* @param tag Optional tag name for the fragment, to later retrieve the
* fragment with {@link FragmentManager#findFragmentByTag(String)
* FragmentManager.findFragmentByTag(String)}.
*
* @return Returns the same FragmentTransaction instance.
*/
public abstract FragmentTransaction replace(@IdRes int containerViewId, Fragment fragment,
@Nullable String tag);
其参数和 add
方法一致
移除
remove
方法:
/**
* Remove an existing fragment. If it was added to a container, its view
* is also removed from that container.
*
* @param fragment The fragment to be removed.
*
* @return Returns the same FragmentTransaction instance.
*/
public abstract FragmentTransaction remove(Fragment fragment);
需要提供要移除的 fragment
对象
实现:
返回栈的使用
由上面操作可知,进行 fragment
的操作如下
- 获取
FragmentTransaction
对象 - 执行
add / replace / remove
操作 - 执行
commit
提交更改
可以将 fragment
更改记录下来,方法是在 commit
之前调用函数 addToBackStack
:
/**
* Add this transaction to the back stack. This means that the transaction
* will be remembered after it is committed, and will reverse its operation
* when later popped off the stack.
*
* @param name An optional name for this back stack state, or null.
*/
public abstract FragmentTransaction addToBackStack(@Nullable String name);
当执行上面的操作后,点击 返回键 能够回退到上一步的 fragment
或者调用 FragmentManager.popBackStack
模拟返回键操作:
/**
* Pop the top state off the back stack. Returns true if there was one
* to pop, else false. This function is asynchronous -- it enqueues the
* request to pop, but the action will not be performed until the application
* returns to its event loop.
*/
public abstract void popBackStack();
修改 MainActivity.java
如下:
public class MainActivity extends AppCompatActivity {
...
private void initView() {
...
btnRemove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// removeFragment();
popFragment();
}
});
}
private void addFragment() {
...
fragmentTransaction.add(R.id.fl_container, onefragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
btnAdd.setEnabled(false);
btnReplace.setEnabled(true);
btnRemove.setEnabled(true);
}
private void replaceFragment() {
...
fragmentTransaction.replace(R.id.fl_container, fragment, "twoFragment");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
...
}
private void removeFragment() {
...
// btnRemove.setEnabled(false);
// btnAdd.setEnabled(true);
}
private void popFragment() {
fragmentManager.popBackStack();
}
}
监听器
还可以设置 FragmentManager.addOnBackStackChangedListener
对返回栈操作进行监听:
/**
* Interface to watch for changes to the back stack.
*/
public interface OnBackStackChangedListener {
/**
* Called whenever the contents of the back stack change.
*/
public void onBackStackChanged();
}
修改 MainActivity.java
如下:
public class MainActivity extends AppCompatActivity implements FragmentManager.OnBackStackChangedListener {
private static final String TAG = "MainActivity";
...s
@Override
public void onBackStackChanged() {
Log.e(TAG, "onBackStackChanged: "+fragmentManager.getBackStackEntryCount());
}
private void initView() {
...
fragmentManager = getSupportFragmentManager();
fragmentManager.addOnBackStackChangedListener(this);
...
}
...
}
与 activity
的事件回调
activity
的事件回调
可以在 fragment
中创建一个回调接口,在 activity
实现该接口即可
比如,在 fragment
中创建一个点击事件:
public interface OnClickListener {
void onFragmentClick(View var1);
}
在创建 fragment
时进行绑定:
public class OneFragment extends Fragment {
OnClickListener mListener;
...
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnClickListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnClickListener");
}
}
...
}
在 activity
中实现 onFragmentClick
方法即可
Note:ClassCastException
属于运行时异常