【Demo记录】Fragment 返回栈

来源:互联网 发布:cocos2d-js webgl 编辑:程序博客网 时间:2024/06/05 16:31

效果

这里写图片描述
toast打印的是返回之前显示的fragment的标记
点击返回键时,不会直接退出activity,而是返回到之前显示的Fragment(当前显示的是首页时,直接退出Activity)


Fragment 知识点

1、Fragment和Activity关联的主要方式在于:添加、替换

通过Activity中Fragment的管理器,将Fragment添加到Activity指定的布局中,每一次添加Fragment都会在原界面的基础上添加Fragment,可以理解为在原Fragment的基础上又覆盖了一层,如果Fragment之间背景透明,可以看到各个添加的Fragment内容重叠,所以,一般在第一个将Fragment显示到界面上时使用addFragment方式,要改变Fragment的内容,则通过replaceFragment来进行。替换的方式,不会出现内容重叠的情况。

2、Fragment 返回栈

Fragment 依附于Activity来做内容的显示,当在Activity中点击返回按钮时,这个Activity将会销毁。想点击返回实现Fragment的返回,而不是直接退出Activity,则需要使用到返回栈。

返回栈的相关操作:入栈、出栈、获取返回栈里的个数

入栈:addToBackStack(@Nullable String name);
示例代码:

FragmentManager mSupportFragmentManager = getSupportFragmentManager();mSupportFragmentManager.beginTransaction()        .replace(R.id.frameLayout_content, fragments[0], "first")        .addToBackStack("first")        .commit();

出栈

popBackStack();//将返回栈里面的栈顶元素pop出栈popBackStack(String name,int flags);//将标记为name之上的元素全部移除,flags表示标记为name的这个元素是否需要出栈,0表示不需要,POP_BACK_STACK_INCLUSIVE表示该元素需要出栈。popBackStack(int id,int flags);//将栈里面位置在id上面的元素都移除,根据flags来判断是否移除该位置的元素。popBackStackImmediate();//和上面相比,只是多了个Immediate 表示立即执行,其余的参数 则和上面一致。popBackStackImmediate(String name,int flags);popBackStackImmediate(int id,int flags);

获取返回栈中元素的个数
getBackStackEntryCount();

期间遇到的问题:在onCreate中执行获取的个数一直为0,解决方案:
在获取个数之前 使用executePendingTransitions();

最后还有一种获取元素个数有问题的操作,在onPressBack中进行的操作,详情 直接跳到文章末尾。

解决方案参考自:
http://stackoverflow.com/questions/13964409/why-fragmentmanagers-getbackstackentrycount-return-zero


Demo

界面设计:

这里写图片描述

Activity Layout:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context="com.tjstudy.radiogrouptab.MainActivity">    <FrameLayout        android:id="@+id/frameLayout_content"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1" />    <RadioGroup        android:id="@+id/radioGroup_tabs"        android:layout_width="match_parent"        android:layout_height="?android:actionBarSize"        android:orientation="horizontal">        <RadioButton            android:id="@+id/tab1"            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:layout_weight="1"            android:background="@drawable/selector_tabs"            android:button="@null"            android:gravity="center"            android:text="第一个界面" />        <RadioButton            android:id="@+id/tab2"            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:layout_weight="1"            android:button="@null"            android:gravity="center"            android:background="@drawable/selector_tabs"            android:text="第二个界面" />        <RadioButton            android:id="@+id/tab3"            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:background="@drawable/selector_tabs"            android:layout_weight="1"            android:button="@null"            android:gravity="center"            android:text="第三个界面" />    </RadioGroup></LinearLayout>

其中涉及到 selector_tabs 是选择器
背景颜色选择器

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <item android:state_checked="true">        <color android:color="#cc0000" />    </item>    <item>        <color android:color="#00cc00" />    </item></selector>

选择器相关:
http://blog.csdn.net/u012391876/article/details/52243797

三个Fragment准备,没有进行其他操作,界面指显示了一个TextView 显示是第几页 第一个Fragment 参考代码

/** * 第一个界面 tab1 */public class FirstFragment extends Fragment {    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {        return inflater.inflate(R.layout.fragment_first, container, false);    }}
<FrameLayout 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"    tools:context="com.tjstudy.radiogrouptab.fragment.FirstFragment">    <TextView        android:layout_width="match_parent"        android:layout_height="match_parent"        android:gravity="center"        android:text="第一个界面" /></FrameLayout>

其他两个Fragment的代码和这个类似-略

重点:Activity的操作
1、 界面默认显示第一页,addFragment1
2、 点击tab的时候,replaceFragment
3、 点击返回键的处理,回退到首页-默认的第一页,当前页已经是首页的情况下,直接结束这个activity。

package com.tjstudy.radiogrouptab;public class MainActivity extends AppCompatActivity implements View.OnClickListener {    private RadioButton tab1;    private RadioButton tab2;    private RadioButton tab3;    private FragmentManager mSupportFragmentManager;    private Fragment[] fragments;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();        initListener();    }    private void initListener() {        tab1.setOnClickListener(this);        tab2.setOnClickListener(this);        tab3.setOnClickListener(this);    }    private void initView() {        tab1 = (RadioButton) findViewById(R.id.tab1);        tab2 = (RadioButton) findViewById(R.id.tab2);        tab3 = (RadioButton) findViewById(R.id.tab3);        //初始化界面        mSupportFragmentManager = getSupportFragmentManager();        fragments = new Fragment[]{new FirstFragment(), new SecondFragment(), new ThirdFragment()};        mSupportFragmentManager.beginTransaction()                .add(R.id.frameLayout_content, fragments[0], "first")//        第一个不添加到栈里面 添加到栈之后 点击返回按钮时,会将fragment出栈 这里出栈之后界面就变成空白的了//                .addToBackStack("first")                .commit();        tab1.setChecked(true);    }    @Override    public void onClick(View v) {        int id = v.getId();        switch (id) {            case R.id.tab1:                mSupportFragmentManager.beginTransaction()                        .replace(R.id.frameLayout_content, fragments[0], "first")                        .addToBackStack("first")//添加到返回栈                        .commit();                break;            case R.id.tab2:                mSupportFragmentManager.beginTransaction()                        .replace(R.id.frameLayout_content, fragments[1], "second")                        .addToBackStack("second")                        .commit();                break;            case R.id.tab3:                mSupportFragmentManager.beginTransaction()                        .replace(R.id.frameLayout_content, fragments[2], "third")                        .addToBackStack("third")                        .commit();                break;        }    }    @Override    public void onBackPressed() {        //需要判断当前界面是不是 就是默认的界面        int backStackEntryCount = mSupportFragmentManager.getBackStackEntryCount();        Toast.makeText(this, "backStackEntryCount:" + backStackEntryCount, Toast.LENGTH_SHORT).show();        if (backStackEntryCount > 0) {            //1、获取返回栈 栈顶元素的标记            String name = mSupportFragmentManager.getBackStackEntryAt(backStackEntryCount - 1).getName();            Toast.makeText(this, name, Toast.LENGTH_SHORT).show();            //2、判断栈顶元素是不是默认界面            Toast.makeText(this, "getTag().name:" + fragments[0].getTag().equalsIgnoreCase(name), Toast.LENGTH_SHORT).show();            if (fragments[0].getTag().equalsIgnoreCase(name)) {                //2.1 是默认界面则 直接退出activity                finish();            } else {    //将栈里面的元素全部回退//        while (mSupportFragmentManager.getBackStackEntryCount() > 0) {//            mSupportFragmentManager.popBackStackImmediate();//        }                //2.2 不是默认界面,则将返回栈中的元素全部出栈--由于第一个界面没有添加到栈 显示的则是第一个界面                mSupportFragmentManager.popBackStackImmediate(0, FragmentManager.POP_BACK_STACK_INCLUSIVE);            }            tab1.setChecked(true);        } else {            finish();        }    }}

为什么在第一次操作添加Fragment到界面上时,不将其添加到返回栈中?
Fragment被添加到返回栈中,点击返回键时,会先执行将Fragment从返回栈中移除的操作,第一次添加Fragment时,将该Fragment添加到返回栈中,此时点返回键时,Fragment被移除,此时界面Fragment区域就变成一片空白了。

获取返回栈中元素个数遇到的问题
在onBackPress中,获取返回栈元素个数 不是预期的值(比预期值少1),没有达到预期效果。解决方案参考上面提供的网址。
super.onPress();影响了相关代码的执行,获取返回栈的个数和进行出栈操作在super.onPress之前执行,由于将super.onPress放到后面,activity会直接退出,这里没有使用super.onPress方法,而是改用finish直接结束activity.


Demo源码

http://download.csdn.net/detail/u012391876/9729927

0 0
原创粉丝点击