Android 底部导航栏实现
底部导航栏的应用非常的广泛。今天就总结下几种实现的方式。
一、Fragment + TextView 实现
前面一篇博客在介绍Fragment 的时候就使用了Fragment + ImageView 实现了一个底部导航栏点击的例子,只要把ImageView 替换为TextView 是一样的实现。这里就详细介绍了,可以看这篇博客Android之Fragment的概述和使用
这种方式每次点击我们都要重置 所有TextView的状态,然后选中点击的TextView
二、RadioGroup + ViewPager 实现
我们只需重写RadioGroup的onCheckedChange,判断checkid即可知道点击的是哪个RadioButton,再给ViewPager 设置监听,让底部导航栏和viewpager同步就行了。
运行效果:
- 新建四个布局文件
这里我放一个布局文件的代码,其他几个都是一样的。
<?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">
<ImageView
android:layout_width="match_parent"
android:layout_height="500dp"
android:src="@drawable/tx4"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我的"
android:textSize="50sp"
android:textColor="#ff0000"
android:layout_gravity="center" />
</LinearLayout>
- 编写我们更换底部导航栏图标的xml,和导入我们的图标,选中和没有选中个一个不同的颜色。这里就给出一个
me_drawable.xml
的例子
分别设置选中和没有选中的图片
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@drawable/me_select"/>
<item android:state_checked="false" android:drawable="@drawable/me_normal"/>
</selector>
- 编写activity_main.xml布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.mq.bottomtoobar2.MainActivity">
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/rg_tab"/>
<RadioGroup
android:id="@+id/rg_tab"
android:layout_width="fill_parent"
android:layout_height="55dp"
android:gravity="center_vertical"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_msg"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:checked="true"
android:drawableTop="@drawable/msg_drawable"
android:gravity="center"
android:paddingLeft="0dp"
android:text="信息" />
<RadioButton
android:id="@+id/rb_people"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:drawableTop="@drawable/people_drawable"
android:gravity="center"
android:paddingLeft="0dp"
android:text="联系人" />
<RadioButton
android:id="@+id/rb_find"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:drawableTop="@drawable/find_drawable"
android:gravity="center"
android:paddingLeft="0dp"
android:text="发现" />
<RadioButton
android:id="@+id/rb_me"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:drawableTop="@drawable/me_drawable"
android:gravity="center"
android:paddingLeft="0dp"
android:text="我" />
</RadioGroup>
</RelativeLayout>
注意: android:button="@null" 属性可以将边上的圈圈去掉。
- 编写MainActivity代码
public class MainActivity extends AppCompatActivity {
private ViewPager mViewPager;
private RadioGroup mRadioGroup;
private RadioButton tab1,tab2,tab3,tab4; //四个单选按钮
private List<View> mViews; //存放视图
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();//初始化数据
//对单选按钮进行监听,选中、未选中
mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
switch (i) {
case R.id.rb_msg:
mViewPager.setCurrentItem(0);
break;
case R.id.rb_people:
mViewPager.setCurrentItem(1);
break;
case R.id.rb_find:
mViewPager.setCurrentItem(2);
break;
case R.id.rb_me:
mViewPager.setCurrentItem(3);
break;
}
}
});
}
private void initView() {
//初始化控件
mViewPager=findViewById(R.id.viewpager);
mRadioGroup=findViewById(R.id.rg_tab);
tab1=findViewById(R.id.rb_msg);
tab2=findViewById(R.id.rb_people);
tab3=findViewById(R.id.rb_find);
tab4=findViewById(R.id.rb_me);
mViews=new ArrayList<View>();//加载,添加视图
mViews.add(LayoutInflater.from(this).inflate(R.layout.msg,null));
mViews.add(LayoutInflater.from(this).inflate(R.layout.people,null));
mViews.add(LayoutInflater.from(this).inflate(R.layout.find,null));
mViews.add(LayoutInflater.from(this).inflate(R.layout.me,null));
mViewPager.setAdapter(new MyViewPagerAdapter());//设置一个适配器
//对viewpager监听,让分页和底部图标保持一起滑动
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override //让viewpager滑动的时候,下面的图标跟着变动
public void onPageSelected(int position) {
switch (position) {
case 0:
tab1.setChecked(true);
tab2.setChecked(false);
tab3.setChecked(false);
tab4.setChecked(false);
break;
case 1:
tab1.setChecked(false);
tab2.setChecked(true);
tab3.setChecked(false);
tab4.setChecked(false);
break;
case 2:
tab1.setChecked(false);
tab2.setChecked(false);
tab3.setChecked(true);
tab4.setChecked(false);
break;
case 3:
tab1.setChecked(false);
tab2.setChecked(false);
tab3.setChecked(false);
tab4.setChecked(true);
break;
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
//ViewPager适配器
private class MyViewPagerAdapter extends PagerAdapter {
@Override
public int getCount() {
return mViews.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view==object;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView(mViews.get(position));
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
container.addView(mViews.get(position));
return mViews.get(position);
}
}
}
三、BottomNavigationView+ViewPager+fragment 实现
这是 Google 给我们提供的一个专门用于底部导航的 View,你只需要在新建 Activity 的时候选择 “Bottom Navigation Activity”就可以了。
运行效果:
BottomNavigationView 的Tab是通过menu 的方式添加的。使用较为简单,不需要你自己定义控件,只需要自己修改他给你定义的menu文件和回调方法
这里不过多的介绍了,大家可以去看一下里面的代码。
四、TabLayout+fragment+viewPager 实现
实现底部导航栏我们很容易想到使用表格布局,下面就是一个个的tab切换viewpager就行。
这种实现方最为常用吧。
运行效果:
- 在build.gradle导入工具包:
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support:support-v4:27.1.1'
- 编写 activity2_main.xml 布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/tablayout"/>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tablayout"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="50dp">
</com.google.android.material.tabs.TabLayout>
</RelativeLayout>
- 编写四个Fragment以及布局
这里给出一个Fragment,其余几个都是一样的。
public class me extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_me, 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.mq.bottomtoobar3.me">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/tx4"/>
</FrameLayout>
- 编写MyAdapt继承FragmentPagerAdapter的适配器
public class MyAdapt extends FragmentPagerAdapter {
private List<Fragment> mFragments;
private List<String> mtitle;
public MyAdapt(@NonNull FragmentManager fm, List<Fragment> mFragments,List<String> mtitle) {
super(fm);
this.mFragments=mFragments;
this.mtitle=mtitle;
}
@NonNull
@Override //返回指定fragment
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override //返回fragment数量
public int getCount() {
return mFragments.size();
}
@Nullable
@Override //获取分页标题
public CharSequence getPageTitle(int position) {
return mtitle.get(position);
}
}
- 编写MainActivity2 代码
public class MainActivity2 extends AppCompatActivity {
private List<Fragment> mFragments; //存放视图
private ViewPager viewPager;
private TabLayout mTabLayout;
private List<String> mtitle; //存放底部标题
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity2_main);
initView();
}
private void initView() {
mTabLayout = findViewById(R.id.tablayout);
viewPager = findViewById(R.id.viewpager);
mFragments=new ArrayList<>();
mFragments.add(new msg());
mFragments.add(new people());
mFragments.add(new find());
mFragments.add(new me());
mtitle=new ArrayList<String>();
mtitle.add("信息");
mtitle.add("联系人");
mtitle.add("发现");
mtitle.add("我的");
//实例化适配器
MyAdapt adapt = new MyAdapt(getSupportFragmentManager(), mFragments, mtitle);
viewPager.setAdapter(adapt);
mTabLayout.setupWithViewPager(viewPager);//给tab设置一个viewpager
//viewpager的监听
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override //选中
public void onPageSelected(int position) {
switch (position){
case 0:
Toast.makeText(MainActivity2.this, "这是信息", Toast.LENGTH_SHORT).show();
break;
case 1:
Toast.makeText(MainActivity2.this, "这是联系人", Toast.LENGTH_SHORT).show();
break;
case 2:
Toast.makeText(MainActivity2.this, "这是发现", Toast.LENGTH_SHORT).show();
break;
case 3:
Toast.makeText(MainActivity2.this, "这是我的", Toast.LENGTH_SHORT).show();
break;
}
}
@Override // //state的状态有三个,0表示什么都没做,1正在滑动,2滑动完毕
public void onPageScrollStateChanged(int state) {
}
});
}
}
小结
底部导航栏实现的方式实在是太多种了,主要就是考虑布局的分配。上面的主页面 内容展示你要用什么去实现,以及下面的底部导航你要用什么去实现,只要可以组合起来并建立监听的一致,就可以实现底部导航栏的功能。
同理底部导航栏的实现也可以做顶部导航栏
今日的分享就到此为止吧!