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重叠出现。