一、利用BottomNavigatiomView实现底部标签栏
不管是微信还是QQ,它们的首屏都在底部展开一栏标签,每个标签对应着一个频道,从而方便用户迅速切换到对应频道。
标签页面主要由两个组成部分
1:一个是位于底部的底部导航视图
2:另一个是位于其上占据剩余屏幕的碎片fragment
每个fragment节点拥有以下四个属性
1:id 指定当前碎片的编号
2:name 指定当前碎片的完整类名路径
3:label 指定当前碎片的标题文本
4:layout 指定当前碎片的布局文件
效果如下
代码如下
Java类
package com.example.chapter12;
import android.os.Bundle;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.example.chapter12.databinding.ActivityTabNavigation2Binding;
public class TabNavigationActivity extends AppCompatActivity {
private ActivityTabNavigation2Binding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityTabNavigation2Binding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
BottomNavigationView navView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_tab_navigation2);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(binding.navView, navController);
}
}
XML文件如下
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu" />
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@id/nav_view"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/mobile_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
二、自定义标签按钮
一般应用的APP下方都会有标签按钮,每个按钮的图标和文字都会随着选中而高亮显示
整合后效果如下
代码如下
Java类
package com.example.chapter12;
import android.os.Bundle;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class TabButtonActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tab_button);
final TextView tv_select = findViewById(R.id.tv_select);
CheckBox ck_tab = findViewById(R.id.ck_tab);
// 给复选框设置勾选监听器
ck_tab.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (buttonView.getId() == R.id.ck_tab) {
String desc = String.format("标签按钮被%s了", isChecked?"选中":"取消选中");
tv_select.setText(desc);
}
}
});
}
}
XML文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="5dp">
<!-- 复选框的背景、文字颜色和顶部图标都采用了状态图形,看起来像个崭新的标签控件 -->
<CheckBox
android:id="@+id/ck_tab"
android:layout_width="100dp"
android:layout_height="60dp"
android:padding="5dp"
android:gravity="center"
android:button="@null"
android:background="@drawable/tab_bg_selector"
android:text="点我"
android:textSize="12sp"
android:textColor="@drawable/tab_text_selector"
android:drawableTop="@drawable/tab_first_selector" />
<TextView
android:id="@+id/tv_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="这里查看标签选择结果"
android:textColor="@color/black"
android:textSize="17sp" />
<View
android:layout_width="match_parent"
android:layout_height="10dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal">
<CheckBox
style="@style/TabButton"
android:checked="true"
android:drawableTop="@drawable/tab_first_selector"
android:text="首页" />
<CheckBox
style="@style/TabButton"
android:drawableTop="@drawable/tab_second_selector"
android:text="分类" />
<CheckBox
style="@style/TabButton"
android:drawableTop="@drawable/tab_third_selector"
android:text="购物车" />
</LinearLayout>
</LinearLayout>
三、结合RadioGroup和ViewPager自定义底部标签栏
因为Android默认定义好的标签样式风格不方便另行调整,况且它也不支持通过左右滑动切换标签,因此如果我们想实现拥有更多花样的标签栏,就需要自己定义专门的底部标签栏了
效果如下
代码如下
Java类
package com.example.chapter12;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.ViewPager;
import android.os.Bundle;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import com.example.chapter12.adapter.TabPagerAdapter;
public class TabPagerActivity extends AppCompatActivity {
private ViewPager vp_content; // 声明一个翻页视图对象
private RadioGroup rg_tabbar; // 声明一个单选组对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tab_pager);
vp_content = findViewById(R.id.vp_content); // 从布局文件获取翻页视图
// 构建一个翻页适配器
TabPagerAdapter adapter = new TabPagerAdapter(getSupportFragmentManager());
vp_content.setAdapter(adapter); // 设置翻页视图的适配器
// 给翻页视图添加页面变更监听器
vp_content.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
// 选中指定位置的单选按钮
rg_tabbar.check(rg_tabbar.getChildAt(position).getId());
}
});
rg_tabbar = findViewById(R.id.rg_tabbar); // 从布局文件获取单选组
// 设置单选组的选中监听器
rg_tabbar.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
for (int pos=0; pos<rg_tabbar.getChildCount(); pos++) {
// 获得指定位置的单选按钮
RadioButton tab = (RadioButton) rg_tabbar.getChildAt(pos);
if (tab.getId() == checkedId) { // 正是当前选中的按钮
vp_content.setCurrentItem(pos); // 设置翻页视图显示第几页
}
}
}
});
}
}
适配器类
package com.example.chapter12.adapter;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import com.example.chapter12.fragment.TabFirstFragment;
import com.example.chapter12.fragment.TabSecondFragment;
import com.example.chapter12.fragment.TabThirdFragment;
public class TabPagerAdapter extends FragmentPagerAdapter {
// 碎片页适配器的构造方法,传入碎片管理器
public TabPagerAdapter(FragmentManager fm) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
// 获取指定位置的碎片Fragment
@Override
public Fragment getItem(int position) {
if (position == 0) {
return new TabFirstFragment(); // 返回第一个碎片
} else if (position == 1) {
return new TabSecondFragment(); // 返回第二个碎片
} else if (position == 2) {
return new TabThirdFragment(); // 返回第三个碎片
} else {
return null;
}
}
// 获取碎片Fragment的个数
@Override
public int getCount() {
return 3;
}
}
XML文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.viewpager.widget.ViewPager
android:id="@+id/vp_content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<RadioGroup
android:id="@+id/rg_tabbar"
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_home"
style="@style/TabButton"
android:checked="true"
android:text="首页"
android:drawableTop="@drawable/tab_first_selector" />
<RadioButton
android:id="@+id/rb_class"
style="@style/TabButton"
android:text="分类"
android:drawableTop="@drawable/tab_second_selector" />
<RadioButton
android:id="@+id/rb_cart"
style="@style/TabButton"
android:text="购物车"
android:drawableTop="@drawable/tab_third_selector" />
</RadioGroup>
</LinearLayout>