Android仿小米商城底部导航栏之二(BottomNavigationBar、ViewPager和Fragment的联动使用)

2023-10-29

简介

在前文《Android仿小米商城底部导航栏(基于BottomNavigationBar)》我们使用BottomNavigationBar控件模仿实现了小米商城底部导航栏效果。接下来更进一步的,我们将通过BottomNavigationBar控件和ViewPager空间的联动使用来实现主界面的滑动导航。

导航是移动应用最重要的方面之一,对用户体验是良好还是糟糕起着至关重要的作用。好的导航可以让一款应用更加易用并且让用户快速上手。相反,糟糕的应用导航很容易让人讨厌,并遭到用户的抛弃。为了打造流畅的用户导航体验,我们不得不依赖智能手机最常见的一个功能:触摸。

触摸改变应用程序的视图是现在最流行一种导航设计。本文中,我们将经过必要的几步来实现应用内的横向滑动导航与底部导航的联动。

基本原理

我们的MainActivity包含了ViewPager组件,它封装了几个不同的子界面,每一界面有一个不同的Fragment。我们要做的第一件事就是声明一个FragmentPagerAdapter,用它在不用的界面Fragment间切换。

ViewPager 如其名所述,是负责翻页的一个 View。准确说是一个 ViewGroup,包含多个 View 页,在手指横向滑动屏幕时,其负责对 View 进行切换。为了生成这些 View 页,需要提供一个 PagerAdapter 来进行和数据绑定以及生成最终的 View 页。

ViewPager 通过 setAdapter() 来建立与 PagerAdapter 的联系。这个联系是双向的,一方面,ViewPager 会拥有 PagerAdapter 对象,从而可以在需要时调用 PagerAdapter 的方法;另一方面,ViewPager 会在 setAdapter() 中调用 PagerAdapter 的 registerDataSetObserver() 方法,注册一个自己生成的 PagerObserver 对象,从而在 PagerAdapter 有所需要时(如 notifyDataSetChanged()或 notifyDataSetInvalidated() 时),可以调用 Observer 的 onChanged() 或 onInvalidated() 方法,从而实现 PagerAdapter 向 ViewPager 方向发送信息。

PageAdapter 是 ViewPager 的支持者,ViewPager 将调用它来取得所需显示的页,而 PageAdapter 也会在数据变化时,通知 ViewPager。这个类也是FragmentPagerAdapter 以及 FragmentStatePagerAdapter 的基类。如果继承自该类,至少需要实现 instantiateItem(), destroyItem(), getCount() 以及 isViewFromObject()。

FragmentPagerAdapter 继承自 PagerAdapter。相比通用的 PagerAdapter,该类更专注于每一页均为 Fragment 的情况。如文档所述,该类内的每一个生成的 Fragment 都将保存在内存之中,因此适用于那些相对静态的页,数量也比较少的那种;如果需要处理有很多页,并且数据动态性较大、占用内存较多的情况,应该使用FragmentStatePagerAdapter。FragmentPagerAdapter 重载实现了几个必须的函数,因此来自 PagerAdapter 的函数,我们只需要实现 getCount(),即可。且,由于 FragmentPagerAdapter.instantiateItem() 的实现中,调用了一个新增的虚函数 getItem(),因此,我们还至少需要实现一个 getItem()。因此,总体上来说,相对于继承自 PagerAdapter,更方便一些。

设置ViewPager的监听事件
当ViewPager的某个页面被选中时,需要相应的选中BottomNavigationBar控件的对应标签。

    viewPager.addOnPageChangeListener(this);

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        bottomNavigationBar.selectTab(position);
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }

设置BottomNavigationBar的监听事件
当BottomNavigationBar控件的某个标签被选中的时候,需要相应的选中ViewPager的对应页面。

    bottomNavigationBar.setTabSelectedListener(this);

    @Override
    public void onTabSelected(int position) {
        viewPager.setCurrentItem(position);
    }

    @Override
    public void onTabUnselected(int position) {

    }

    @Override
    public void onTabReselected(int position) {

    }

实现效果

实现效果

主要代码

主界面布局文件activity_main,xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/activity_main"
    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"
    tools:context="com.rainsong.mishop.MainActivity">

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <com.ashokvarma.bottomnavigation.BottomNavigationBar
        android:id="@+id/bottom_navigation_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"/>

</LinearLayout>

MainActivity.java

package com.rainsong.mishop;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;

import com.ashokvarma.bottomnavigation.BottomNavigationBar;
import com.ashokvarma.bottomnavigation.BottomNavigationItem;
import com.rainsong.mishop.adapter.SectionsPagerAdapter;
import com.rainsong.mishop.fragment.CatagoryFragment;
import com.rainsong.mishop.fragment.DiscoverFragment;
import com.rainsong.mishop.fragment.HomeFragment;
import com.rainsong.mishop.fragment.UserCentralFragment;

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

public class MainActivity extends AppCompatActivity implements BottomNavigationBar
        .OnTabSelectedListener, ViewPager.OnPageChangeListener {

    private ViewPager viewPager;
    private BottomNavigationBar bottomNavigationBar;
    private List<Fragment> fragments;

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

        initView();
    }

    private void initView() {
        initBottomNavigationBar();
        initViewPager();
    }

    private void initBottomNavigationBar() {
        bottomNavigationBar = (BottomNavigationBar) findViewById(R.id.bottom_navigation_bar);
        bottomNavigationBar.setTabSelectedListener(this);
        bottomNavigationBar.clearAll();
        bottomNavigationBar.setMode(BottomNavigationBar.MODE_FIXED);
        bottomNavigationBar.setBackgroundStyle(BottomNavigationBar.BACKGROUND_STYLE_STATIC);
        bottomNavigationBar
                .addItem(new BottomNavigationItem(R.drawable.icon_main_home_selected, R.string.home)
                        .setInactiveIconResource(R.drawable.icon_main_home_normal)
                        .setActiveColorResource(R.color.orange))
                .addItem(new BottomNavigationItem(R.drawable.icon_main_category_selected, R
                        .string.category)
                        .setInactiveIconResource(R.drawable.icon_main_category_normal)
                        .setActiveColorResource(R.color.orange))
                .addItem(new BottomNavigationItem(R.drawable.icon_main_discover_selected, R
                        .string.discover)
                        .setInactiveIconResource(R.drawable.icon_main_discover_normal)
                        .setActiveColorResource(R.color.orange))
                .addItem(new BottomNavigationItem(R.drawable.icon_main_mine_selected, R.string.mine)
                        .setInactiveIconResource(R.drawable.icon_main_mine_normal)
                        .setActiveColorResource(R.color.orange))
                .initialise();
    }

    private void initViewPager() {
        viewPager = (ViewPager) findViewById(R.id.view_pager);

        fragments = new ArrayList<Fragment>();
        fragments.add(new HomeFragment());
        fragments.add(new CatagoryFragment());
        fragments.add(new DiscoverFragment());
        fragments.add(new UserCentralFragment());

        viewPager.setAdapter(new SectionsPagerAdapter(getSupportFragmentManager(), fragments));
        viewPager.addOnPageChangeListener(this);
        viewPager.setCurrentItem(0);
    }

    @Override
    public void onTabSelected(int position) {
        viewPager.setCurrentItem(position);
    }

    @Override
    public void onTabUnselected(int position) {

    }

    @Override
    public void onTabReselected(int position) {

    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        bottomNavigationBar.selectTab(position);
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
}

SectionsPagerAdapter.java

package com.rainsong.mishop.adapter;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

import java.util.List;

/**
 * Created by maxliaops on 17-1-6.
 */

public class SectionsPagerAdapter extends FragmentPagerAdapter {
    List<Fragment> fragments;

    public SectionsPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);
        this.fragments = fragments;
    }

    @Override
    public Fragment getItem(int position) {
        return fragments.get(position);
    }

    @Override
    public int getCount() {
        return fragments.size();
    }
}

Demo:https://github.com/maxliaops/android-exercise/tree/master/MiShop

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android仿小米商城底部导航栏之二(BottomNavigationBar、ViewPager和Fragment的联动使用) 的相关文章

  • 我们如何从 Android 通知中提取 bigpicturestyle 图像?

    我有一个通知侦听器服务 可以读取来自其他应用程序的通知 经用户许可 并提取所有数据 能够访问除通知展开视图中显示的图像之外的所有内容 我也在阅读 EXTRA PICTURE 意图值 if extras containsKey Notific
  • 如何在android中获取MapView API?

    如何在android中获取MapView API thanks Android 文档中实际上是这么写的 你好 地图视图 http developer android com guide tutorials views hello mapvi
  • 视图无法解析为类型

    这里的视图似乎有什么问题 我该如何解决它 错误 视图无法解析为类型 public void onItemClick AdapterView
  • Android 从 C++ 端播放原始音频

    我需要能够在 Android 系统的 C 端以自定义文件格式传输音频 我正在致力于移植自定义媒体播放器 并且需要能够打开自定义文件并从中传输音频 这很重要 因为我认为从性能角度来看将整个播放器移植到 JAVA 是不可行的 并且通过 JNI
  • Auto-value-gson出现接口错误,注册一个InstanceCreator?

    我有一个如下所示的接口类 public interface Species String name And a Human实现的类 AutoValue使用类型适配器 AutoValue public abstract class Human
  • 多种语言的多种字体

    我最近在开发应用程序时遇到了一种情况 我必须在文本视图中显示不同的语言 目前我正在展示一些使用字体 字体像这样 Typeface tf Typeface createFromAsset this getAssets DroidHindi t
  • 如何实现 ALTER TABLE 的示例[重复]

    这个问题在这里已经有答案了 我已经多次问过这个问题 但尚未得到完整的答案 如何实现 ALTER TABLE 语句以向数据库添加列 有人可以给我举个例子吗 请阅读SQLite ALTER TABLE 参考 http sqlite org la
  • 在android中从JSON生成listview

    我对 Android 完全陌生 目前正在尝试从从我的服务器中提取的 JSON 数组生成列表视图 我已经阅读了很多教程 但没有运气 有一种独特的方法可以做到这一点 请您指出一些适合开始的资源 我读过了this http www josecgo
  • SQLite FTS4 使用特殊字符进行搜索

    我有一个 Android 应用程序 它使用 FTS4 虚拟表在 SQLite 数据库中搜索数据 它工作正常 但是当表中的数据包含特殊字符 如 或 时 SQLite MATCH 函数不会给出任何结果 我现在迷路了 谢谢 注意 默认的分词器真的
  • Android 辅助功能服务检测通知

    我试图让我的应用程序在显示通知时进行检测 我已在设置应用程序中启用它并且onServiceConnected确实接到电话 但是当我创建通知或通过 gmail 应用程序接收电子邮件时 什么也没有发生 onAccessibilityEvent没
  • Cordova + android:无法从应用程序打开拨号盘或邮件意图

    我有一个奇怪的问题 我无法从应用程序中打开带有预定义号码或邮件意图的拨号盘 我正在使用 netbeans 8 0 1 创建 cordova 应用程序 我的 Cordova 版本是 4 0 0 我按照步骤创建了一个应用程序 并选择了 Hell
  • 警报对话框中的 Webview 不显示内容

    我正在开发一个 Android 应用程序 我需要在网络视图和警报对话框上显示一个网站 该站点显示在网络视图中 但不显示在警报对话框中 到目前为止 这是我的代码 WebView WebView myWebView WebView v find
  • 如何将设备屏幕位置转换为发送事件位置?

    我知道关于input tap x yshell 命令 但是 我想了解如何 使用执行单击sendevent命令 我能够通过以下命令实现它 sendevent dev input event5 3 53 X sendevent dev inpu
  • PhoneGap 1.4 封装 Sencha Touch 2.X - 性能怎么样?

    我正在构建一个多平台平板电脑应用程序 仅使用其 Webview 使用 Phonegap 1 4 对其进行包装 然后使用 Sencha Touch 2 框架发挥我的魔力 我所说的多平台是指 iOS 5 X 和 Android 3 0 目前 到
  • 为什么 Google 建议将库复制到您的树中?

    谷歌的Play 服务 API 的使用说明 http developer android com google play services setup html 例如 说 将 extras google google play service
  • 找不到数据库路径是不可能的

    我对 android 开发很陌生 现在我正在尝试通过扩展 SQLiteOpenHelper 的类创建数据库 我确信数据存储在我的 Nexus 7 我用来测试应用程序的设备 上的某个位置 但是我找不到数据库的路径 我四处寻找其他类似的问题 所
  • 在android中从SD卡上传图像到facebook

    我无法从 SD 卡上传 Facebook 上的图像 我使用了下面的代码 但它没有给我错误 但同时它没有上传图像 byte data null try FileInputStream fis new FileInputStream filep
  • Android:分配内存失败

    我正在尝试创建一个具有 2047 mb 内存的模拟器 当我运行它时 我收到此错误 2011 02 22 14 24 14 Emulator 2011 02 22 14 24 14 Emulator This application has
  • android系统用户和linux root用户有什么区别

    当我将手机连接到电脑并使用adb shell与我的手机通信并输入的命令ps命令输出当前在我的手机上运行的进程信息 我发现有两个特殊用户 一个是root 另一个是system 据我所知 Android是基于linux的 所以root用户是最大
  • ARM Chromebook 上的 Android 开发环境?

    我尝试了多次安装和使用安卓工作室 https developer android com studio index html on an ARM Chromebook C100P https archlinuxarm org platfor

随机推荐

  • C++11之 unique_ptr

    原文地址为 http www drdobbs com cpp c11 uniqueptr 240002708 在C 11中加入了很多的新特性 unique ptr一枝独秀 对于动态分配的内存对象 它简单有效 虽然它不是万能的 但是它做的已经
  • Java 并发编程中篇 -(JMM、CAS 原理、Volatile 原理)

    并发编程已完结 章节如下 Java 并发编程上篇 Synchronized 原理 LockSupport 原理 ReentrantLock 原理 Java 并发编程中篇 JMM CAS 原理 Volatile 原理 Java 并发编程下篇
  • java实现机房存活主机多线程实现

    主要使用java原生开发 实现多线程ping 在扫描存活主机时能够减少ping的时间提高运行效率 已完成课程设计代码上传中 2022 5 5
  • MySQL最终弹-并发(脏读,不可重复读,幻读及区别),JDBC的使用和安装,最全万字

    一 并发基本概念 并发的基本意思 什么是并发呢 简单的理解就是同一时间执行 服务器同一时刻 给多个客户端提供服务 这两个客户端都可以给服务器提交事务 如果提交两个事务 改不同的表还没啥影响 假如要改相同的表 这时候可能会出现麻烦 二 脏读
  • ubuntu下protobuf安装使用(详解)

    1 安装 1 1安装前的环境 以下几个库都有安装 sudo apt get install autoconf automake libtool curl make g unzip 1 2安装 注意 以下命令在超级用户下执行 sudo apt
  • 机器学习(Machine Learning)&深度学习(Deep Learning)资料

    机器学习 Machine Learning 深度学习 Deep Learning 资料 Chapter 1 注 机器学习资料 篇目一 https github com ty4z2008 Qix blob master dl md 共500条
  • linux中主线程退出后子线程的状态

    1 运行如下代码 即是简单创建一个子线程 主线程直接结束 然后在子线程中每间隔一秒就打印一个HELLO 利用ps ef查看进程状态 发现没有主线程和子线程都不在 即是主线程退出后子线程也会退出 2 运行如下代码 增加利用pthread ex
  • js动态添加与删除ul中的li

    方法一 createElement li 方式方法二 innerHTML方式方法一实例 参考 http zhidao baidu com question 175951279 html
  • 2021-02-05

    一个 C 转 GO 的程序员的自白 GO 一个文件下载过滤需求 var file been found lock sync Mutex var file been found map string int make map string i
  • 我的 PhpStorm 设置

    可能因为 PhpStorm 版本不同的原因 你找不到如下设置的地点 此时可以在设置界面搜索设置项的关键字 软件字体 进入设置 Settings gt Appearance Behavior gt Appearance 勾选Override
  • 华为OD机试真题 Java 实现【报数游戏】【2022Q4 100分】

    一 题目描述 100个人围成一圈 每个人有一个编码 编号从1开始到100 他们从1开始依次报数 报到为M的人自动退出圈圈 然后下一个人接着从1开始报数 直到剩余的人数小于M 请问最后剩余的人在原先的编号为多少 二 输入描述 输入一个整数参数
  • SQL基本的表修改及其它命令

    对于已经建好的表 有时可能因为业务的变动或者设计时考虑的不周全而需要进行列的调整 包 括增加一个新的列 修改一个列 为列定义一个缺省值 删除一个列等 对应语句语法分别如下 ALTER TABLE table ADD column datat
  • pytorch中一维卷积conv1d,参数含义,为何转置

    pytorch中一维卷积conv1d 参数含义 为何转置 在Pytorch中 一维卷积是一种非常常用的运算 但是对于刚刚入门的新手 了解此函数的用法仍是一个比较费力的挑战 本文简单介绍一下此函数的常用参数的意义以及此函数的用法 链接 cov
  • Node.js 利用高阶函数 ( 柯里化 ) 并发写入流、读取流(Stream)

    首先 介绍Stream实例对象的方法 data 读数据时触发 end 数据读取完毕时触发 error 在接收和写入过程中发生错误时触发 finish 所有数据已被写入到底层系统时触发 今天 我们利用node对stream对象的支持 利用高阶
  • 在Windows下使用Anaconda安装TesnsorFlow 2.x

    作者 弗拉德 来源 弗拉德 公众号 fulade me 下载 Anaconda 首先打开Anaconda官网找到网页底部 由于最新的Anaconda支持Python3 8版本 而TesnorFlow最高支持到Python3 7 我特意查了一
  • java.lang.IllegalStateException: Failed to load ApplicationContext

    问题描述 mvn clean install的时候报的如下异常 紧接着又往下翻了一下日志还有一个这个错误 按正常来说通过 可以取pom当中的properties标签的值呀 但是可以发现编译过后的application当中的值并没有被替换 解
  • 2022年最新版黑马程序员Java学习路线

    工欲善其事 必先利其器 自学Java的同学 必备的自学五部曲 学习路线图 学习教程 工具 书籍 面试 一 Java学习路线图 学习路线图说明 二 学习教程推荐 阶段一Java基础 具备Java语言编程基础和IO 多线程 网络编程等开发能力
  • Zstack 挂载云盘,在Windows下面看不到解决方法

    原因 在使用 Zstack 私有云时 创建 WinServer2019 时 想添加一块数据云盘 但是添加好后 进入系统看不到硬盘 主要是因为添加的云盘驱动是 virtio 格式 所以要安装相关驱动 1 查看挂载的云盘 root zstack
  • 【避坑】minio临时凭证STS实现上传,下载

    一 背景 以minio作为图床 采用用户到minio服务器的点对点使用方式 将上传用户的长期凭证放在客户端 app或者web端 带来极大的风险 通常通过临时凭证STS签名的方式实现 简单的逻辑关系图如下 二 minio服务docker安装
  • Android仿小米商城底部导航栏之二(BottomNavigationBar、ViewPager和Fragment的联动使用)

    简介 在前文 Android仿小米商城底部导航栏 基于BottomNavigationBar 我们使用BottomNavigationBar控件模仿实现了小米商城底部导航栏效果 接下来更进一步的 我们将通过BottomNavigationB