Android---简易的底部导航栏

news2024/12/24 9:16:48

目录

一、activity_main.xml布局

二、给ViewPager2 创建适配器

三、ViewPager2 数据源

四、MainActivity.java类

 1、初始化数据源。

2、ViewPager2 页面改变监听

3、BottomNavigationView 的每个 item 点击的监听

 这里简单演示实现效果,实现快速开发,并没有太好的UI界面。当掌握好了知识点,再来优化界面。实现上面的效果主要用到 ViewPager2 + Fragment + BottomNavigationView

一、activity_main.xml布局

        这里只有两个控件。第一个 ViewPager2,用来放 Fragment。第二个是 BottomNavigationView 实现底部导航。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    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"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".MainActivity">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/main_viewPager"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="0dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="0dp"
        android:layout_marginBottom="19dp"
        app:layout_constraintBottom_toTopOf="@+id/main_bottomNavigationView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/main_bottomNavigationView"
        android:layout_width="0dp"
        android:layout_height="78dp"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginBottom="5dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/main_viewPager"
        app:menu="@menu/bottomnavigationitem"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

        给底部导航增加菜单按钮。在 BottomNavigationView 里添加属性 app:menu="@menu/bottomnavigationitem"。在 res 目录下 New --> Directory 新建一个menu目录。在menu目录上 New --> Menu Source File 新建一个 bottomnavigationitem.xml 文件。

        在bottomnavigationitem.xml 里添加一个 item 就是在 底部导航栏里添加了一个可点击的 tab 按钮。注意,item 里面的 icon 属性你可以自己找一下好看的icon,这里简单用 mipmap 里的 ic_launcher.webp 来作为 icon。

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/fragment_1"
        android:icon="@mipmap/ic_launcher"
        android:title="T1"/>
    <item
        android:id="@+id/fragment_2"
        android:icon="@mipmap/ic_launcher"
        android:title="T2"/>
    <item
        android:id="@+id/fragment_3"
        android:icon="@mipmap/ic_launcher"
        android:title="T3"/>
    <item
        android:id="@+id/fragment_4"
        android:icon="@mipmap/ic_launcher"
        android:title="T4"/>
    <item
        android:id="@+id/fragment_5"
        android:icon="@mipmap/ic_launcher"
        android:title="T5"/>

</menu>

二、给ViewPager2 创建适配器

        ViewPager2 是高级 UI。通过适配器 Adapter 来适配数据源。创建一个 MyFragmentStateAdapter.class 类,继承 FragmentStateAdapter,实现两个方法 createFragment() 和 getItemCount()。

        注意:

        1、ViewPager 是与 FragmentPagerAdapter 搭配的。而 FragmentPagerAdapter 继承自 PagerAdapter。而 FragmentPagerAdapter 已经被官方给废弃了。

        2、ViewPager2 是与 FragmentStateAdapter 搭配的。而 FragmentStateAdapter 继承自 RecyclerView.Adapter。因此可以用到 RecyclerView 的性质,比如垂直滑动效果。

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;

import java.util.List;

public class MyFragmentStateAdapter extends FragmentStateAdapter {

    private List<Fragment> mData;

    public MyFragmentStateAdapter(FragmentActivity fragmentActivity, List<Fragment> mData) {
        super(fragmentActivity);
        this.mData = mData;
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        return mData.get(position);
    }

    @Override
    public int getItemCount() {
        return mData == null ? 0 : mData.size();
    }
}

三、ViewPager2 数据源

        创建一个 Fragment 来作为 ViewPager2 的数据源。

public class MyFragment extends Fragment{


    /**
     * 的到当前Fragment 的一个实例
     */
    public static MyFragment newInstance(int position){
        Bundle bundle = new Bundle();
        bundle.putInt("Position", position);
        MyFragment fragment = new MyFragment();
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Log.d(TAG, tabIndex + "fragment" + "onCreate");
    }


    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);
    }


}

四、MainActivity.java类

 1、初始化数据源。

/**
     * 初始化数据
     */
    private List<Fragment> initData(){
        mData = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            mData.add(MyFragment.newInstance(i));
        }
        return mData;
    }

2、ViewPager2 页面改变监听

        ViewPager2 里对页面改变的监听是 OnPageChangeCallback(); ViewPager 是 OnPageChangeListener(), 但是已经被废弃了。

        BottomNavigationView.setSelectedItemId(itemID) 根据itemID 设置选中的 item。当滑动 Fragment 时,BottomNavigationView 的每个 item 也会相应的改变。做到每个Fragment 与 下面BottomNavigationView 的每个 item 绑定。

ViewPager2.OnPageChangeCallback onPageChangeCallback = new ViewPager2.OnPageChangeCallback() {
        @Override
        public void onPageSelected(int position) {
            super.onPageSelected(position);
            int itemID = R.id.fragment_1;
            switch (position) {
                case 0:
                    itemID = R.id.fragment_1;
                    break;
                case 1:
                    itemID = R.id.fragment_2;
                    break;
                case 2:
                    itemID = R.id.fragment_3;
                    break;
                case 3:
                    itemID = R.id.fragment_4;
                    break;
                case 4:
                    itemID = R.id.fragment_5;
                    break;
                default:
                    break;
            }
            //TODO 当Fragment滑动改变时,底部的Tab也跟着改变
            mBottomNavigationView.setSelectedItemId(itemID);
        }
    };

3、BottomNavigationView 的每个 item 点击的监听

        对于底部导航栏 item 的监听应该是 OnNavigationItemSelectedListener,但是该方法已经被 google 官方给废弃了,所以这里用 OnItemSelectedListener 来代替。

        ViewPager.setCurrentItem() 方法,设置当前 Viewpager 要加载的item (Fragment),这里做到 ViewPager2 的每一个 Fragment 与 底部导航栏的每个 item 绑定

NavigationBarView.OnItemSelectedListener onItemSelectedListener = new NavigationBarView.OnItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            // 点击Tab, 切换对应的 Fragment
            switch (item.getItemId()) {
                case R.id.fragment_1:
                    //TODO 当点击 Tab 时,ViewPager 也切换到对应的 Fragment
                    mViewPager.setCurrentItem(0, true);
                    return true;
                case R.id.fragment_2:
                    mViewPager.setCurrentItem(1, true);
                    return true;
                case R.id.fragment_3:
                    mViewPager.setCurrentItem(2, true);
                    return true;
                case R.id.fragment_4:
                    mViewPager.setCurrentItem(3, true);
                    return true;
                case R.id.fragment_5:
                    mViewPager.setCurrentItem(4, true);
                    return true;
            }
            return false;
        }
    };

MainActivity的完整代码

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.widget.ViewPager2;

import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;

import com.example.viewpager2_demo.adapter.MyFragmentStateAdapter;
import com.example.viewpager2_demo.fragment.MyFragment;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.navigation.NavigationBarView;

import java.util.ArrayList;
import java.util.List;

@RequiresApi(api = Build.VERSION_CODES.M)
public class MainActivity extends AppCompatActivity {


    private ViewPager2 mViewPager;
    private BottomNavigationView mBottomNavigationView;

    private List<Fragment> mData;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mViewPager = findViewById(R.id.main_viewPager);
        mBottomNavigationView = findViewById(R.id.main_bottomNavigationView);
        // 设置适配器
        mViewPager.setAdapter(new MyFragmentStateAdapter(this, initData()));
        mViewPager.setOffscreenPageLimit(1); //设置页面缓存的个数,默认1个
        //设置底部导航栏 item 点击的监听
        mBottomNavigationView.setOnItemSelectedListener(onItemSelectedListener);

        // 设置 ViewPager2 页面改变的监听
        mViewPager.registerOnPageChangeCallback(onPageChangeCallback);

    }

    ViewPager2.OnPageChangeCallback onPageChangeCallback = new ViewPager2.OnPageChangeCallback() {
        @Override
        public void onPageSelected(int position) {
            super.onPageSelected(position);
            int itemID = R.id.fragment_1;
            switch (position) {
                case 0:
                    itemID = R.id.fragment_1;
                    Log.d("HL", "1");
                    break;
                case 1:
                    itemID = R.id.fragment_2;
                    Log.d("HL", "2");
                    break;
                case 2:
                    itemID = R.id.fragment_3;
                    Log.d("HL", "3");
                    break;
                case 3:
                    itemID = R.id.fragment_4;
                    Log.d("HL", "4");
                    break;
                case 4:
                    itemID = R.id.fragment_5;
                    Log.d("HL", "5");
                    break;
                default:
                    break;
            }
            //TODO 当Fragment滑动改变时,底部的Tab也跟着改变
            mBottomNavigationView.setSelectedItemId(itemID);
        }
    };

    NavigationBarView.OnItemSelectedListener onItemSelectedListener = new NavigationBarView.OnItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            // 点击Tab, 切换对应的 Fragment
            switch (item.getItemId()) {
                case R.id.fragment_1:
                    //TODO 当点击 Tab 时,ViewPager 也切换到对应的 Fragment
                    mViewPager.setCurrentItem(0, true);
                    return true;
                case R.id.fragment_2:
                    mViewPager.setCurrentItem(1, true);
                    return true;
                case R.id.fragment_3:
                    mViewPager.setCurrentItem(2, true);
                    return true;
                case R.id.fragment_4:
                    mViewPager.setCurrentItem(3, true);
                    return true;
                case R.id.fragment_5:
                    mViewPager.setCurrentItem(4, true);
                    return true;
            }
            return false;
        }
    };

    /**
     * 初始化数据
     */
    private List<Fragment> initData(){
        mData = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            mData.add(MyFragment.newInstance(i));
        }
        return mData;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/124279.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mmdetection从入门到精通(一)-汇总目录

&#xff11;.简介 MMDetection 是商汤出品的集成了目标检测&#xff0f;实例分割分割&#xff0f;全景分割几个方面顶级模型组合的,模块化的&#xff0c;基于 PyTorch 的目标检测开源工具箱。是深度学习工作者的必备工具&#xff0c;非常有必要深入掌握。 近期汇总一下从入…

今年最后一场官方活动

阅读本文大概需要 1.6 分钟。2022 年 12 月 26&#xff0c;新型冠状病毒肺炎正式更名为了新型冠状病毒感染&#xff0c;不再纳入《中华人民共和国国境卫生检查疫法》 规定的检疫传染病管理。文字层面上&#xff0c;这意味着我们口中的疫情&#xff0c;结束了。然而我却认为并没…

Django学习 Day9

1.F对象 一个F对象代表数据库中某条记录的字段的信息。 作用&#xff1a; 通常是对数据库中的字段的值在不获取的情况下进行操作 用于类属性&#xff08;字段&#xff09;之间的比较。 语法&#xff1a; From django.db.models import F F(‘列名’)例子: 所有Book数据表中的…

云游戏的2022:破局、新生、元宇宙

文|智能相对论 作者|青月 如果说2021年是「元宇宙元年」&#xff0c;那么2022年更像是元宇宙的「祛魅之年」&#xff0c;在这一年里&#xff0c;原本处在狂奔状态下的元宇宙正在褪去虚火。 在这样的大环境下&#xff0c;由于在实时性、兼容性、无限开创等关键特性的理念上的…

99. 激光炸弹——二维前缀和

地图上有 N 个目标&#xff0c;用整数 Xi,Yi 表示目标在地图上的位置&#xff0c;每个目标都有一个价值 Wi。 注意&#xff1a;不同目标可能在同一位置。 现在有一种新型的激光炸弹&#xff0c;可以摧毁一个包含 RR 个位置的正方形内的所有目标。 激光炸弹的投放是通过卫星定…

eclipse中安装ERMaster

eclipse中安装ERMaster 简介 参考网址&#xff1a; https://www.bilibili.com/video/BV1R4411a73T/?p22&spm_id_from333.880.my_history.page.click&vd_source42661b67a37800001020550eb4a4c45e 主要看这 3 集 ERMaster 在 jeesite 官网的介绍项目 参考网址&#x…

systemd(二)单元配置文件

概述 对于系统中的每一个单元&#xff08;unit&#xff09;都有一个配置文件&#xff0c;用于指示systemd如何启动或停止这个单元。 配置文件格式 [Unit]区块 [Unit]区块通常是配置文件的第一个区块&#xff0c;用来定义单元的元数据&#xff0c;以及配置与其他单元的关系。…

多线程模式下保证事物的一致性

目录前置InsertBatchSuccessServiceImpl.javaInsertBatchErrorServiceImpl.java效果图前置 在一些特殊的场景下, 我们需要一些特定的操作. 比如我有一个接口, 做如下操作, 需要保持事物的一致性, 即: 全部成功则提交, 一个异常则全部回滚: 1.insert订单、(耗时1秒) 2.insert订单…

4、MYSQL常用函数(字符串函数)

目录 1、concat函数&#xff1a; 2、insert(str,x,y,instr)函数&#xff1a; 3、lower(str)和upper(str)函数&#xff1a; 4、left(str,x)和right(str,x)函数&#xff1a; 5、lpad(str,n,pad) 和rpad(str,n,pad) 函数&#xff1a; 6、ltrim(str)和rtrim(str)函数&#xff…

【大厂高频真题100题】《除自身以外数组的乘积》 真题练习第19题 持续更新~

除自身以外数组的乘积 给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请不要使用除法,且在 O(n) 时间复杂度内完成…

微软补丁包下载

Microsoft Update Cataloghttps://www.catalog.update.microsoft.com/Home.aspxMicrosoft Update CatalogMicrosoft Update Cataloghttps://www.catalog.update.microsoft.com/Home.aspx

城市通信管线资源管理解决方案

01 背景 随着新基建发展&#xff0c;智慧项目如火如荼&#xff0c;网络畅通、高速成为了刚需&#xff0c;城市通信网络管线资源重要性不言而喻&#xff0c;在实际项目中&#xff0c;我们也不难发现有关于“通信网络管线管理”“光缆资源管理”项目愈发增多&#xff0c;大多客户…

(五)JSP

一、JSP 概述 JSP&#xff08;全称&#xff1a;Java Server Pages&#xff09;&#xff1a;Java 服务端页面。是一种动态的网页技术&#xff0c;其中既可以定义HTML、JS、CSS等静态内容&#xff0c;还可以定义Java代码的动态内容&#xff0c;也就是 JSP HTML Java 。二、JSP …

基于注解的AOP之准备工作以及各种通知

目录 基于注解的AOP之准备工作以及各种通知 1. 技术说明 2. 准备工作 ①添加依赖 ②准备被代理的目标资源 3. 创建切面类并配置 在Spring的配置文件中配置&#xff1a; ​​​​​​4. 各种通知 各种通知的执行顺序&#xff1a; 基于注解的AOP之准备工作以及各种通知 …

C++【B树】【B+树】

文章目录一、什么是B树1.为什么要存在B树&#xff1f;2.B树的规则二、B树的插入三、B树的实现时间复杂度四、B树1.B树的分类过程五、B*树六、B树系列的应用1.MyISAM2.InnoDB一、什么是B树 相比于我们别的数据结构&#xff0c;我们的B树更加适合进行外查找 B树也可以进行内查找…

元启发式算法-模拟退火算法MATLAB实现

元启发式算法-模拟退火算法MATLAB实现 模拟退火介绍 模拟退火算法来源于固体退火原理&#xff0c;是一种基于概率的算法&#xff0c;将固体加温至充分高&#xff0c;再让其徐徐冷却&#xff0c;加温时&#xff0c;固体内部粒子随温升变为无序状&#xff0c;内能增大&#xff0…

SpringBoot系列教程之定义接口返回类型的几种方式

本文节选自 《Spring WEB专栏》 WEB系列】 定义接口返回类型的几种方式 实现一个 web 接口返回 json 数据&#xff0c;基本上是每一个 javaer 非常熟悉的事情了&#xff1b;那么问题来了&#xff0c;如果我有一个接口&#xff0c;除了希望返回 json 格式的数据之外&#xff0c…

Linux内核学习笔记——内核页表隔离KPTI机制

接前文。 一步一步理解CPU芯片漏洞&#xff1a;Meltdown与Spectre ARM系列之MMU TLB和ASID基础概念介绍。 一、Meltdown & Spectre 漏洞 Meltdown 和 Spectre 这两个漏洞厉害的地方就在于&#xff0c;利用现代CPU speculative execution (预测执行)的漏洞&#xff0c;在…

退役记——破铜烂铁的一生

写在前面 今天刚刚结束大三上的所有课程。我慢慢鼓起勇气去整理这段零碎的竞赛记忆&#xff0c;或许是最终也没拿到一个满意的奖项&#xff0c;来给我的竞赛生涯画上一个圆满的句号。 我该怎么回忆这破铜烂铁的一生&#xff0c;上万次尝试提交、数以千计的习题、上百次练习赛…

01、Java 数据结构:数据结构和算法的概述

数据结构和算法的概述1 参考教材2 数据结构2.1 数据的逻辑结构2.2 数据的存储结构2.3 数据的运算3 基本的数学概念的复习3.1 函数的定义3.2 极限3.3 对数4 算法4.1 算法的基本特性4.2 算法设计的要求4.3 时间复杂度和空间复杂度是衡量算法优劣的重要指标1 参考教材 主要参考的…