底部导航栏设计
- 1.依赖配置
- 2.tabbar的UI实现
- 3.tabbar的逻辑绑定
- 4.tabbar的滑动与点击联动
其实,常见的Android和微信小程序一样,通常最下面一排需要有一排导航栏,可以通过点击导航栏图标和滑动实现页面跳转,具体实现使用的是Android的
ViewPager2
。
1.依赖配置
首先需要在build.gradle
引入对应的依赖:
implementation 'androidx.viewpager2:viewpager2:1.0.0'
2.tabbar的UI实现
在MainActivity中引入viewPager2
(viewPager的升级版本,现在用的较多)配置:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"android:orientation="vertical"android:id="@+id/activity_main"tools:context=".MainActivity"><androidx.viewpager2.widget.ViewPager2android:id="@+id/viewPager"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"/><!--引入tabbarUI设计,独立出来,方便详细调整--><include layout="@layout/bottom_layout" />
</LinearLayout>
这里我使用的tabbar设计如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/table_bar"android:layout_width="match_parent"android:layout_height="55dp"android:background="@color/gray"android:gravity="center"android:orientation="horizontal"><LinearLayoutandroid:id="@+id/tab_home"android:layout_width="0dp"android:layout_height="match_parent"android:layout_gravity="center"android:layout_weight="1"android:gravity="center"android:orientation="vertical"tools:ignore="Suspicious0dp"><ImageViewandroid:id="@+id/iv_home"android:layout_width="32dp"android:layout_height="32dp"android:background="@drawable/tab_home" /><TextViewandroid:id="@+id/text_home"android:layout_width="32dp"android:layout_height="32dp"android:gravity="center"android:text="首页" /></LinearLayout><LinearLayoutandroid:id="@+id/tab_focus"android:layout_width="0dp"android:layout_height="match_parent"android:layout_gravity="center"android:layout_weight="1"android:gravity="center"android:orientation="vertical"tools:ignore="Suspicious0dp"><ImageViewandroid:id="@+id/iv_focus"android:layout_width="32dp"android:layout_height="32dp"android:background="@drawable/tab_focus" /><TextViewandroid:id="@+id/text_focus"android:layout_width="32dp"android:layout_height="match_parent"android:gravity="center"android:text="关注" /></LinearLayout><LinearLayoutandroid:id="@+id/tab_subscribe"android:layout_width="0dp"android:layout_height="match_parent"android:layout_gravity="center"android:layout_weight="1"android:gravity="center"android:orientation="vertical"tools:ignore="Suspicious0dp"><ImageViewandroid:id="@+id/iv_subscribe"android:layout_width="32dp"android:layout_height="32dp"android:background="@drawable/tab_subscribe" /><TextViewandroid:id="@+id/text_subscribe"android:layout_width="32dp"android:layout_height="32dp"android:gravity="center"android:text="订阅" /></LinearLayout></LinearLayout>
设计解释:其实就是使用了如下三个相同的代码块:
<LinearLayoutandroid:id="@+id/tab_home"android:layout_width="0dp"android:layout_height="match_parent"android:layout_gravity="center"android:layout_weight="1"android:gravity="center"android:orientation="vertical"tools:ignore="Suspicious0dp"><ImageViewandroid:id="@+id/iv_home"android:layout_width="32dp"android:layout_height="32dp"android:background="@drawable/tab_home" /><TextViewandroid:id="@+id/text_home"android:layout_width="32dp"android:layout_height="32dp"android:gravity="center"android:text="首页" /></LinearLayout>
图标加上导航页的名字,使用android:layout_weight="1"
,类似于前端的flex=1
,其实就是为了把底部导航栏分成多个等分, android:layout_gravity="center"
,类似于前端的justify-content:center
使得各个导航栏中的内容居中。
补充关于按钮的点亮和未点亮状态设计,在Android的可选按钮中设计selector
资源:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:drawable="@drawable/home_default" android:state_selected="false"/><item android:drawable="@drawable/home_active" android:state_selected="true"/>
</selector>
3.tabbar的逻辑绑定
有了UI还需要实现逻辑上的绑定,可以在MainActivity里面设计一个初始化函数:
//viewPager相关的代码比较固定,可以直接搬运,然后自己初始化对应的Fragment页面实现定制化
public void initPager() {viewPager = findViewById(R.id.viewPager);ArrayList<Fragment> fragments = new ArrayList<>();//添加Fragment页面fragments.add(new FragmentHome());fragments.add(new FragmentFocus());fragments.add(new FragmentSubscribe());FragmentPagerAdapter PagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager(), getLifecycle(), fragments);viewPager.setAdapter(PagerAdapter);viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {@Overridepublic void onPageSelected(int position) {super.onPageSelected(position);changeTab(position);//监听用户滑动,这里面的changeTab是自定义函数为了将滑动和点击tabbar的视觉效果统一}@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {super.onPageScrolled(position, positionOffset, positionOffsetPixels);}@Overridepublic void onPageScrollStateChanged(int state) {super.onPageScrollStateChanged(state);}});
}
下面详细说一下Fragment的实现,直接继承Android自带的FragmentList,详细原理可以参考菜鸟教程关于fragment的介绍:
public class FragmentFocus extends ListFragment {
//根据提示重写里面的方法,其实类似于一个Activity,只是通过FragmentPagerAdapter捆绑在一起
}
4.tabbar的滑动与点击联动
设计思路入下:
标记当前正在访问的页面,当修改了页面就将当前正在访问的页面设置成false
,然后修改正在访问的页面标记为跳转目标页面,主要是为了实现tabbar的点亮和关闭:
public void initTabView() {
//tab_home 是为了获取整个图标和文字部分iv_home 获取的是图标,目的是将图标设计成点亮态和未访问态。tab_home = findViewById(R.id.tab_home);tab_focus = findViewById(R.id.tab_focus);tab_subscribe = findViewById(R.id.tab_subscribe);
//前面提到过,setOnClickListener是由于MainActivity实现了点击接口,便于统一管理点击事件tab_home.setOnClickListener(this);tab_focus.setOnClickListener(this);tab_subscribe.setOnClickListener(this);iv_home = findViewById(R.id.iv_home);iv_focus = findViewById(R.id.iv_focus);iv_subscribe = findViewById(R.id.iv_subscribe);iv_home.setOnClickListener(this);iv_focus.setOnClickListener(this);iv_subscribe.setOnClickListener(this);iv_home.setSelected(true);iv_current = iv_home;}@Override//点击切换public void onClick(View view) {switch (view.getId()) {case R.id.tab_home:viewPager.setCurrentItem(0);break;case R.id.tab_focus:viewPager.setCurrentItem(1);break;case R.id.tab_subscribe:viewPager.setCurrentItem(2);break;}}
这样是不够的,还需要绑定用户对页面的滑动:
private void changeTab(int position) {iv_current.setSelected(false);switch (position) {case 0:iv_home.setSelected(true);iv_current = iv_home;break;case 1:iv_focus.setSelected(true);iv_current = iv_focus;break;case 2:iv_subscribe.setSelected(true);iv_current = iv_subscribe;break;}}
最后将changeTab
函数放在registerOnPageChangeCallback
相关的函数里面即可。