Fragment使用率非常大,最常见的就是APP首页,和Activity组成的首页,例如微信主界面,今天就来看一看Fragment切换是如何操作的。

布局文件:

看微信的主页面,实则就是一个Activity,通过下方的几个按钮进行fragment的切换,首先我们现在写一下Activity的布局,既然要用到Fragment,我们在布局中就需要一个FrameLayout来装载Fragment,然后在下方写几个按钮,这里我们用RadioButton:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <FrameLayout
        android:id="@+id/fl"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <RadioGroup
        android:id="@+id/rg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <RadioButton
            android:id="@+id/btn1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@null"
            android:checked="true"
            android:drawablePadding="6dp"
            android:drawableTop="@drawable/selector_discovery_btn"
            android:gravity="center"
            android:text="fragment1"
            android:textColor="#333333" />

        <RadioButton
            android:id="@+id/btn2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@null"
            android:drawablePadding="6dp"
            android:drawableTop="@drawable/selector_insight_btn"
            android:gravity="center"
            android:text="fragment2"
            android:textColor="#333333" />

        <RadioButton
            android:id="@+id/btn3"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@null"
            android:drawablePadding="6dp"
            android:drawableTop="@drawable/selector_mentions_btn"
            android:gravity="center"
            android:text="fragment3" />
    </RadioGroup>


</LinearLayout>

代码中,RadioGroup控件里面有很多重复代码,可以写到style.xml文件中统一引用,这里就不做介绍了,可以看我之前的博文。

drawableTop中我们引用了一个自己写的XML文件,目的是实现当我们选中其中一个按钮时,这个按钮高亮,其他按钮变灰。这里需要提供两张图片,一个高亮,一个灰的图片来写,我贴出代码,大家可以看一看:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_discovery_pressed" android:state_checked="true" />
    <item android:drawable="@drawable/ic_discovery_normal" android:state_checked="false" />
</selector>

OK ,布局文件写完了,我们还需要三个Fragment:

public class Fragment1 extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_fragment1,container,false);
    }
}

 

public class Fragment2 extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_fragment2, container, false);
    }
}
public class Fragment3 extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_fragment3, container, false);
    }
}

OK,到现在所有准备工作都差不多了,然后我们开始在Activity中来切换这三个Fragment:

package sound.zcj.myapplication;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.FrameLayout;
import android.widget.RadioGroup;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener {
    private RadioGroup rg;
    private FrameLayout fl;
    //声明三个Fragment
    private Fragment1 fragment1;
    private Fragment2 fragment2;
    private Fragment3 fragment3;
    //实例化一个Fragment用来记录当前展示在眼前的Fragment
    private Fragment currentFragment = new Fragment();
    //用来装三个Fragment的list
    private List<Fragment> fragments = new ArrayList<>();
    private int position = 0;//记录当前fragment索引位置
    //记录当前显示的Fragment的position的key值
    private static final String CURRENT_FRAGMENT = "STATE_FRAGMENT_SHOW";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        fl = findViewById(R.id.fl);
        //通过ID找到RadioGroup
        rg = findViewById(R.id.rg);
        //当内存重启时,获取我们保存的索引下标position
        if (savedInstanceState != null) {
            position = savedInstanceState.getInt(CURRENT_FRAGMENT, 0);
            fl.removeAllViews();
        }
        //实现RadioGroup监听
        rg.setOnCheckedChangeListener(this);
        //初始化Fragment并添加到list中
        initFragment();
        //展示Fragment
        showFragment(position);
    }

    /**
     * 初始化Fragment
     */
    private void initFragment() {
        fragment1 = new Fragment1();
        fragment2 = new Fragment2();
        fragment3 = new Fragment3();
        fragments.add(fragment1);
        fragments.add(fragment2);
        fragments.add(fragment3);
    }

    /**
     * @param position 展示Fragment
     */
    private void showFragment(int position) {
        //获取FragmentTransaction
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        if (fragments.get(position).isAdded()) {
            //如果需要展示出的这个Fragment是被添加过的,那么直接隐藏当前Fragment,展示这个Fragment
            transaction.hide(currentFragment).show(fragments.get(position));
        } else {
            //如果需要展示的这个Fragment没有被添加过,那么隐藏当前Fragmnet并且添加这个Fragment
            transaction.hide(currentFragment).add(R.id.fl, fragments.get(position), "" + position);//第三个参数给添加的fragment增加一个标识
        }
        //把这个Fragment设置为当前Fragment
        currentFragment = fragments.get(position);
        //提交
        transaction.commit();
    }

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        switch (checkedId) {
            //这里position的值与fragments对应
            case R.id.btn1:
                position = 0;
                break;
            case R.id.btn2:
                position = 1;
                break;
            case R.id.btn3:
                position = 2;
                break;
        }
        //展示Fragment
        showFragment(position);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        //保存当前fragment的position
        outState.putInt(CURRENT_FRAGMENT, position);
        super.onSaveInstanceState(outState);
    }
}

代码中的注释很详细,大家可以看一下,需要提一点的是,重写onSaveInstanceState()方法保存position的目的是为了防止fragment重叠出现。