Android 实现同个Activity中存在多个Fragment多次切换之后依次返回(二)(自维护栈的简单使用)

本文记录如何实现同个Activity中存在多个Fragment多次切换依次返回之后或者任意返回。

依次返回

这里写图片描述
思路:自己定义一个栈,将我们每次显示的Fragment放到我们的栈里面,想要依次返回的时候就从栈顶开始弹栈,如果想要返回到任意Fragment的时候,就去栈中找到这个Fragment
实现这个需求需要用到Stack这个类了
首先简单介绍下Stack,首先它是继承Vector,在Vector基础上,做了一些拓展,主要方法如下

方法名返回类型说明
emptyboolean判断是否为空
peekE返回栈顶元素
popE弹出栈顶元素,并将该元素返回
pushE将元素压入栈
searchint返回最靠近顶端的目标元素到顶端的距离。

1,首先需要3个Fragment

public class Fragment1 extends Fragment{

    @Override
    public View onCreateView(LayoutInflater inflater,  ViewGroup container,  Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment1,container,false);
        TextView mTextView = (TextView) view.findViewById(R.id.tv_fragment_content);
        mTextView.setText("Fragment1");
        return view;
    }
}
public class Fragment2 extends Fragment1 {

    @Override
    public View onCreateView(LayoutInflater inflater,  ViewGroup container,  Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment1,container,false);
        TextView mTextView = (TextView) view.findViewById(R.id.tv_fragment_content);
        mTextView.setText("Fragment2");
        return view;
    }
 }
public class Fragment3 extends Fragment1{

    @Override
    public View onCreateView(LayoutInflater inflater,  ViewGroup container,  Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment1,container,false);
        TextView mTextView = (TextView) view.findViewById(R.id.tv_fragment_content);
        mTextView.setText("Fragment3");
        return view;
    }

}

xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout           xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"       android:layout_width="match_parent"
android:layout_height="match_parent">
    <TextView
        android:id="@+id/tv_fragment_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:textSize="40sp"
        android:text="--"
        />
</LinearLayout>

有了3个Fragment之后,我们要实现的效果跟之前一样,依次切换3个Fragment然后通过按返回键依次返回之前的Fragment

下面是Activity的代码:
为什么纯代码写布局,因为工作所迫

public class StackActivity extends FragmentActivity {
    private Stack<Fragment> mFragmentStack = new Stack<>();//自己维护要处理Fragment的栈,这么做的好处是可以灵活的使用里面保存的Fragmtnt
    private Fragment mContentFragment,MainFragment;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LinearLayout mParentLayout = new LinearLayout(this); //最外层布局
        mParentLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
        mParentLayout.setOrientation(LinearLayout.VERTICAL);

        LinearLayout mContentLayout = new LinearLayout(this);//内容布局
        LinearLayout.LayoutParams mContentParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0);
        mContentParams.weight = 1;
        mContentLayout.setLayoutParams(mContentParams);
        mContentLayout.setId(R.id.tv_fragment_content);

        Button toggleFragment = new Button(this);//下面按钮
        toggleFragment.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dp2px(40)));
        toggleFragment.setText("toggle");
        toggleFragment.setOnClickListener(mToggleClickListener);

        mParentLayout.addView(mContentLayout);
        mParentLayout.addView(toggleFragment);

        Window mWindow = getWindow();
        mWindow.setContentView(mParentLayout);

        MainFragment = new Fragment1();
        mFragmentStack.push(MainFragment);//将元素添加到栈
        getSupportFragmentManager().beginTransaction().add(R.id.tv_fragment_content,MainFragment,"fragment1").commit();    


    }

    /**
     * 切换Fragment 这里的if条件是防止多次点击相同元素多次进栈
     * 可以根据自己业务灵活变动
     */
    protected View.OnClickListener mToggleClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if(mFragmentStack.size() <= 1){
                mContentFragment = new Fragment2();
                mFragmentStack.push(mContentFragment);//将元素添加到栈
                getSupportFragmentManager().beginTransaction().replace(R.id.tv_fragment_content,mContentFragment,"fragment1").commit(); 
            }else if(mFragmentStack.size() == 2){
                mContentFragment = new Fragment3();
                showStacks(mFragmentStack);
                getSupportFragmentManager().beginTransaction().replace(R.id.tv_fragment_content,mContentFragment,"fragment1").commit();             
            }
        }
    };

    /**
     * 返回键
     * 触发栈里面的元素弹栈,栈顶开始
     * 这里因为往栈里面塞了2个元素所以第一次弹栈的是最后添加的Fragment ->fragment2
     */
    @Override
    public void onBackPressed() { //返回键
        if(!mFragmentStack.isEmpty()) {
            mContentFragment = mFragmentStack.pop();
            getSupportFragmentManager().beginTransaction().replace(R.id.tv_fragment_content, mContentFragment, "fragment1").commit();  

        }else
            finish();
    }

    public void showStacks(Stack<Fragment> stack){
        if(stack.size() == 0){
            Log.e("TAG","栈里面是空的");
        }else{
            Enumeration mEnum = stack.elements();//得到stack中的枚举对象
            while(mEnum.hasMoreElements()){
                Log.e("TAG","elements : "+ mEnum.nextElement());
            }
        }
    }
}
   /**
     * dp转换为px
     * @param inparam
     * @return
     */
    public int dp2px(float inparam) {
        float destiny = getResources().getDisplayMetrics().density;
        return (int) (destiny * inparam + 0.5f);
    }

这是最基础的依次返回,也可以按照自己的意愿返回到任意Fragment,只要存在在我们的栈中,则可以随意拿出来使用

任意返回

这里写图片描述

上面的search方法,这个会返回目标元素到顶端的距离。
然后我们可以用VectorElementAt方法来获取到当前的对象

//这里只做了直接返回第一个Fragment,其他的没有处理
    @Override
    public void onBackPressed() { //返回键
        if(!mFragmentStack.isEmpty()) {
           mContentFragment = mFragmentStack.elementAt(mFragmentStack.size() - mFragmentStack.search(MainFragment));
            getSupportFragmentManager().beginTransaction().replace(R.id.tv_fragment_content, mContentFragment, "fragment1").commit();
        }else
            finish();
    }
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值