自从Android3.0引入Fargment之后,在Activity中使用底部导航进行Fragment的切换已经越来越普遍,或者可以说已经成为了移动应用的标配,而本篇文章我总结了项目中常用的几种实现导航的方式,分别是RadioGroup、Tablayout、RadioGroup+反射和FragmentTabHost四种实现方式,包含底部和顶部的双导航界面的实现,实现的结果类似下图所示:
Github下载地址:https://github.com/huohaoliz/BottomNavigation
一、使用RadioGroup+Fragment实现底部导航,使用TabLayout+Fragment实现顶部导航
1,RadioGroup+Fragment的形式是之前开发中比较受欢迎,使用比较多的一种实现形式,所以把它排到第一位。好了不扯了,直接代码走起:
首先,在radiogroup.xml中的布局文件是:
我们需要对每个RadioButton的图片资源做一个选择器,在drawable文件夹下添加四个选择器,内容是(这是首页的图片选择器,其他与此类似就不贴代码了):
之后我们还要对选中的RadioButton添加字体颜色的选择器:
之后进入Actiivity中,实现代码:
public class RadioGroupActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener {
private RadioGroup mRadioGroup;
private Fragment[] mFragments;
private FrameLayout mLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_radio_group);
getSupportActionBar().hide();
initView();
initFragment();
setListener();
}
private void setListener() {
//对RadioGroup设置监听事件(监听点击选择)
mRadioGroup.setOnCheckedChangeListener(this);
}
private void initFragment() {
//初始化要显示的Fragment数组
mFragments=new Fragment[4];
mFragments[0]=new HomepageFragment();
mFragments[1]=new SubscriptionFragment();
mFragments[2]=new FindFragment();
mFragments[3]=new MineFragment();
//获取Fragment管理器
FragmentManager manager=getSupportFragmentManager();
//获取事物(使用v4包下)
FragmentTransaction transaction=manager.beginTransaction();
//默认选中HomepageFragment替换Framelayout
transaction.replace(R.id.fl_radio_show,mFragments[0]);
//提交事物
transaction.commit();
//默认点击首页
mRadioGroup.check(R.id.rb_radio_homepage);
}
private void initView() {
mRadioGroup= (RadioGroup) findViewById(R.id.rg_radio_navigation);
mLayout= (FrameLayout) findViewById(R.id.fl_radio_show);
}
@Override
public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) {
//写法与默认点击页面的相同
FragmentManager manager=getSupportFragmentManager();
FragmentTransaction transaction=manager.beginTransaction();
switch(checkedId){
case R.id.rb_radio_homepage:
transaction.replace(R.id.fl_radio_show,mFragments[0]);
break;
case R.id.rb_radio_subscription:
transaction.replace(R.id.fl_radio_show,mFragments[1]);
break;
case R.id.rb_radio_find:
transaction.replace(R.id.fl_radio_show,mFragments[2]);
break;
case R.id.rb_radio_mine:
transaction.replace(R.id.fl_radio_show,mFragments[3]);
break;
}
transaction.commit();
}
}
到此底部导航就已经完成,实现效果如下图所示:
2,在HomepageFragment中使用Tablayout+Fragment实现顶部导航
首先Tablayout是Android5.0发布的Design包中的组件,所以我们在使用之前必须加入Design包的依赖(这里不会就自己百度吧)。然后在Homepage的资源文件中的布局如下:
Tablayout的属性(此处只是给出用到的三个属性,其他常用的属性会在Tablayout+Fragment中给出):
app:tabIndicatorColor="@color/colorPrimary" //下边指示横线的颜色
app:tabSelectedTextColor="@color/textChecked" //Text选中的文字颜色
app:tabTextColor="@color/textUnChecked" //没有选中的文字颜色
在HomepageFragment中的代码是:
public class HomepageFragment extends Fragment {
private ViewPager mViewPager;
private TabLayout mTabLayout;
private ListmFragments;
private ListmTitles;
private HomepageAdapter mAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.fragment_homepage, container, false);
initView(view);
initData(view);
setData();
return view;
}
private void setData() {
mViewPager.setAdapter(mAdapter);
//设置Viewpager和Tablayout进行联动
mTabLayout.setupWithViewPager(mViewPager);
// //将标题设置可以左右摇动而不是移动
// mTabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
// //设置预加载页数
// mViewPager.setOffscreenPageLimit(3);
}
private void initData(View view) {
//初始化导航标题,如果是title在json数据中,在初始化的时候可以使用异步任务加载的形式添加
mTitles=new ArrayList<>();
mTitles.add("热门");
mTitles.add("分类");
mTitles.add("榜单");
//初始化Fragment
mFragments=new ArrayList<>();
for (int i = 0; i
用到的Viewpager的Adapter代码是:
public class HomepageAdapter extends FragmentPagerAdapter {
private List mFragments;
private List mTitles;
public HomepageAdapter(FragmentManager fm, List framents, List titles) {
super(fm);
mFragments = framents;
mTitles = titles;
}
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return mFragments == null ? 0 : mFragments.size();
}
@Override
public CharSequence getPageTitle(int position) {
return mTitles.get(position);
}
}
最后所实现的效果如下所示:
二、使用Tablayout+Fragment实现底部导航
注意:之后三种实现方式不再实现顶部导航,只实现底部导航,而在第二种方式中将详细介绍Tablyout的用法及属性。
1,首先我们先总结一下Tablayout的基本使用(和顶部导航不同的方式实现)
第一种使用先看布局文件:
在代码中:
mTabLayout.addTab(mTabLayout.newTab().setText("Title1"));
mTabLayout.addTab(mTabLayout.newTab().setText("Title2"));
mTabLayout.addTab(mTabLayout.newTab().setText("Title3"));
mTabLayout.addTab(mTabLayout.newTab().setText("Title4"));
第二种使用方式(布局):
二种方式实现的结果相同,如下图所示:
下边我们总结一下Tablayout的属性用法:
app:tabSelectedTextColor=" " //改变选中字体的颜色
app:tabTextColor=" " //改变未选中字体的颜色
app:tabBackground=" " //改变整个TabLayout的颜色app:tabIndicatorColor=" " //改变指示器下标的颜色
app:tabTextAppearance=" " //改变Tablayout的内部字体大小
app:tabPadding="xxdp" //内部子控件的Padding值
app:paddingEnd="xxdp" //设置整个Tablayout的Padding值
app:paddingStart="xxdp"
app:tabMaxWidth="xxdp" //设置最小和最大的tab宽度
app:tabMinWidth="xxdp"
app:tabContentStart="xxdp" //设置Tablayout开始位置的偏移量
tabLayout.addTab(tabLayout.newTab().setText("Tab 1").setIcon(R.mipmap.ic_launcher));//为Tablayout添加图片
app:tabMode=“scrollable” //这个属性用于tab比较多的情况下,实现的结果如下图:
app:tabIndicatorHeight=" "//改变指示器下标的高度
app:tabIndicatorHeight="0dp"//当设置为0时就会去掉指示器下标
2,通过Tablayout+Fragment实现底部导航
首先布局文件很简单:
给Tablayout设置style样式:
切换页面使用了ViewPager和Fragment,所以我们的适配器Adapter的内容:
public class TablayoutAdapter extends FragmentPagerAdapter {
private ListmFragments;
private ListmTitles;
public TablayoutAdapter(FragmentManager fm, ListmFragments, ListmTitles) {
super(fm);
this.mFragments=mFragments;
this.mTitles=mTitles;
}
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return mFragments==null?0:mFragments.size();
}
@Override
public CharSequence getPageTitle(int position) {
return mTitles.get(position);
}
}
最后是TablayoutActivity中的代码:
public class TablayoutActivity extends AppCompatActivity {
private TabLayout mTabLayout;
private ViewPager mViewPager;
private ListmFragments;
private TablayoutAdapter mAdapter;
private ListmTitles;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tablayout);
getSupportActionBar().hide();
initView();
initData();
setData();
setListener();
}
private void setListener() {
}
private void setData() {
mViewPager.setAdapter(mAdapter);
mTabLayout.setupWithViewPager(mViewPager);
for (int i = 0; i ();
mTitles.add("首页");
mTitles.add("订阅");
mTitles.add("发现");
mTitles.add("我的");
mFragments=new ArrayList<>();
for (int i = 0; i
drawable=getResources().getDrawable(R.drawable.hometablayout);//这是一个已经过时的方法,
//现在是最新的方法是传入两个参数,但需要的最低版本有限制(Call requires API level 21 (current min is 15)):
drawable=getResources().getDrawable(R.drawable.hometablayout,null);所以自己根据需要自己选择
上边注释的图片选择器要根据控件选择对应的属性,选择器内容如下:
以上就是Tablayout+ViewPager+Fragment实现底部导航的所有内容,实现的结果如下图所示:
本来准备四种方式实现底部导航,但篇幅较大所以把下边两种方式写到下一遍博客中,我在源码中添加各个Fragment的生命周期方法Log,可以自己运行比较这几种实现方式。从我自己的开发经历以及Fragment的生命周期的比较,我推荐使用反射机制实现底部导航,并且反射也是你进阶需要掌握的一个知识点。
源码下载地址(前两种方式):http://download.csdn.net/detail/huohao_blogs/9851738
另两种实现博客地址:http://blog.csdn.net/huohao_blogs/article/details/72725391
四种实现方式源码地址:http://download.csdn.net/detail/huohao_blogs/9852863