一些相关API
1、Fragment常用的三个类: android.app.Fragment 定义android.app.FragmentManager 用于在Activity中操作Fragmentandroid.app.FragmentTransaction 保证一些列Fragment操作的原子性。事务 2、FragmentManager可以做的事情:
- 使用findFragmentById (适用于在静态fragment,不常用)或 findFragmentByTag (适用于动态加载的fragment,常用)获取activity中存在的fragment
- 使用 popBackStack()将fragment从后台堆栈中弹出 (模拟用户按下BACK 命令)
- 使用 addOnBackStackChangeListener()注册一个监听后台堆栈变化的listener
- 开启一个事务 FragmentTransaction transaction = fm.benginTransatcion()
- transaction.add() 往Activity中添加一个Fragment
- transaction.remove() 从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁
- transaction.replace() 使用另一个Fragment替换当前的Fragment,实际上就是remove()+add()
- transaction.hide() 隐藏当前的Fragment,仅仅是设为不可见,并不会销毁
- transaction.show() 显示之前隐藏的Fragment,在使用之前要判断是否为空以及是否隐藏
- detach() 会将【view】从【UI】中移除,和remove()不同,此时fragment的【状态】依然由FragmentManager维护
- attach() 重建【view】视图,附加到【UI】上并显示
- transatcion.commit() 提交一个事务,注意:commit方法一定要在Activity.onSaveInstance()之前调用。
- 比如:我在FragmentA中的EditText填了一些数据,当切换到FragmentB时,如果希望回到A还能看到数据,则适合你的就是hide和show,当然了不要使劲在那new实例,进行下非null判断;而如果不希望保留用户操作,你可以使用remove() + add(),或者replace()。
- 在不考虑回退栈的情况下,remove会销毁整个Fragment实例,而detach则只是销毁其【视图】结构,【实例】并不会被销毁。那么二者怎么取舍使用呢?如果你的当前Activity一直存在,那么在不希望保留用户操作的时候,你可以优先使用detach。
Fragment回退栈-Activity
类似于Android系统为Activity维护一个任务栈,我们也可以通过Activity维护一个回退栈来保存每次Fragment事务发生的变化。 如果你将Fragment任务添加到回退栈,当用户点击后退按钮时,将看到上一次的保存的Fragment。一旦Fragment完全从后退栈中弹出,用户再次点击后退键,则退出当前Activity。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.add(R.id.id_content, new MyFragment(fm, 1), "ONE");
//注意第一个Fragment若加入回退栈,当点击Back键后仅仅是把此Fragment干掉了,并不会退出应用。实际将会出现白板!
//transaction.addToBackStack("");//如果不加这句,点击后会直接退出应用
transaction.commit();
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="@+id/id_content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#fff" >
</FrameLayout>
</RelativeLayout>
Fragment回退栈-Fragment
public class MyFragment extends Fragment implements OnClickListener { private FragmentManager fm; private int num; /** * 请设置num=1 */ public MyFragment(FragmentManager fm, int num) { this.fm = fm; this.num = num; } private Button mBtn; private TextView tv; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment, container, false); tv = (TextView) view.findViewById(R.id.tv); //若onCreateView被调用了,TextView的数值也会跟着变 tv.setText(new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.CHINA).format(new Date())); mBtn = (Button) view.findViewById(R.id.btn); mBtn.setText("Fragment--" + num); mBtn.setOnClickListener(this); return view; } @Override public void onClick(View v) { FragmentTransaction transaction = fm.beginTransaction(); switch (num) { case 1: //添加到了回退栈后Fragment的实例虽然不会被销毁,但是视图层次依然会被销毁,即会重新调用onDestoryView和onCreateView transaction.replace(R.id.id_content, new MyFragment(fm, 2), "Fragment--" + num); break; case 2: //这里我们没有使用replace,而是先隐藏了当前的Fragment,然后添加了新的Fragment实例,最后将事务添加到回退栈 transaction.hide(this); //当从第三个Fragment返回时,第二个Fragment并没有更新 transaction.add(R.id.id_content, new MyFragment(fm, 3), "Fragment--" + num); break; case 3: Toast.makeText(getActivity(), "最后一个了", Toast.LENGTH_SHORT).show(); return;//这里使用return } //如果不添加事务到回退栈,前一个Fragment实例会被销毁,点击后会直接退出应用 transaction.addToBackStack(""); transaction.commit(); } }
<?xml version="1.0" encoding="UTF-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:id="@+id/btn" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="#ccf" android:gravity="center" android:text="点击进入下一个Fragment" android:textColor="#000" android:textSize="18sp" /> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/btn" android:layout_centerHorizontal="true" android:ellipsize="end" android:gravity="center" android:singleLine="true" android:text="内容" android:textColor="#f00" android:textSize="18sp" /> </RelativeLayout>