Android Design Library之二: BottomNavigationView

news/2023/12/9 4:21:19 标签: 移动开发

http://blog.magicer.xyz/2017/...

BottomNavitagionView出现之前,我们首先底部的导航栏大多是使用RadioGroup+RadioButton的特性来实现。现在官方为我们提供了另外的一条路。先来尝试下。

Demo

打开官方文档里面就有示例程序,比着敲一遍,看下效果。

 <android.support.design.widget.BottomNavigationView
        android:layout_width="match_parent"
        android:layout_height="55dp"
        android:layout_alignParentBottom="true"
        android:layout_gravity="center"
        android:gravity="center"
        app:itemIconTint="#009877"
        app:itemTextColor="#009877"
        app:paddingStart="10dp"
        app:paddingEnd="10dp"
        app:itemBackground="@color/white"
        app:menu="@menu/bottom_nav"/>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/menu_nav_android"
        android:icon="@drawable/ic_android_black_36dp"
        app:showAsAction="ifRoom"
        android:title="Android"/>
    <item
        android:id="@+id/menu_nav_lock"
        android:icon="@drawable/ic_lock_black_36dp"
        app:showAsAction="ifRoom"
        android:title="Lock"/>
    <item
        android:id="@+id/menu_nav_group_work"
        android:icon="@drawable/ic_group_work_black_36dp"
        app:showAsAction="ifRoom"
        android:title="Work"/>

</menu>

效果如下

clipboard.png

嗯。效果还是不错的。但是有时候我们需要的是颜色的变化,这个时候我们需要一个color。在res下的color文件夹下创建一个文件名为bottom_nav的文件内容如下。

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

    <item
        android:color="@color/nav_checked"
        android:state_checked="true"/>

    <item
        android:color="@color/nav_unchecked"
        android:state_checked="false"/>
</selector>

之后为BottomNavitagionView设置上就可以了。
效果如下

clipboard.png

        app:itemIconTint="@color/bottom_nav"
        app:itemTextColor="@color/bottom_nav"

问题

真的就这么就完了么? too young,too simple。我们底部的菜单项肯定不一定是3个。如果是4个。我们试一下,再加菜单项。很简单为menu再添加个item。来看下效果:

clipboard.png

WTF

来看下源码看看到底发生了什么?
BottomNavigationView的源码

    private final MenuBuilder mMenu;
    private final BottomNavigationMenuView mMenuView;
    private final BottomNavigationPresenter mPresenter = new BottomNavigationPresenter();
    private MenuInflater mMenuInflater;
    //.....省略代码
    public void inflateMenu(int resId) {
        mPresenter.setUpdateSuspended(true);
        getMenuInflater().inflate(resId, mMenu);
        mPresenter.setUpdateSuspended(false);
        mPresenter.updateMenuView(true);
    }

我们看到。其中主要有这几个属性,通过查看代码我们可以看到。BottomNavigationPresenter来连接MenuBottomNavigationMenuView的。
BottomNavigationPresenter的部分代码

    private MenuBuilder mMenu;
    private BottomNavigationMenuView mMenuView;
    
    @Override
    public void initForMenu(Context context, MenuBuilder menu) {
        mMenuView.initialize(mMenu);
        mMenu = menu;
    }
    ....省略...
    @Override
    public void updateMenuView(boolean cleared) {
        if (mUpdateSuspended) return;
        if (cleared) {
            mMenuView.buildMenuView();
        } else {
            mMenuView.updateMenuView();
        }
    }

我们可以看到。更新MenuView的方法是通过Presenter来调用的。其内部的代码

  public void buildMenuView() {
        mShiftingMode = mMenu.size() > 3;
        for (int i = 0; i < mMenu.size(); i++) {
            mPresenter.setUpdateSuspended(true);
            mMenu.getItem(i).setCheckable(true);
            mPresenter.setUpdateSuspended(false);
            BottomNavigationItemView child = getNewItem();
            mButtons[i] = child;
            child.setIconTintList(mItemIconTint);
            child.setTextColor(mItemTextColor);
            child.setItemBackground(mItemBackgroundRes);
            child.setShiftingMode(mShiftingMode);
            child.initialize((MenuItemImpl) mMenu.getItem(i), 0);
            child.setItemPosition(i);
            child.setOnClickListener(mOnClickListener);
            addView(child);
        }
        mActiveButton = Math.min(mMenu.size() - 1, mActiveButton);
        mMenu.getItem(mActiveButton).setChecked(true);
    }

这里我们应该就看出来端倪了。mShiftingMode是个boolean值,当menu的长度大于三时,就为true。也就为每一个BottomNavigationItemView 设置上了child.setShiftingMode(mShiftingMode); true。在这里每一个BottomNavigationItemView就是一个tab
BottomNavigationItemView的代码中我们可以看到。其填充的布局为R.layout.design_bottom_navigation_item布局中有两个TextView(smallLabel和largeLabel) 和一个ImageView(icon),详细的代码自己搜一下吧。在design包中,这里就不贴出来了。

if (mShiftingMode) {
            if (checked) {
                LayoutParams iconParams = (LayoutParams) mIcon.getLayoutParams();
                iconParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
                iconParams.topMargin = mDefaultMargin;
                mIcon.setLayoutParams(iconParams);
                mLargeLabel.setVisibility(VISIBLE);
                ViewCompat.setScaleX(mLargeLabel, 1f);
                ViewCompat.setScaleY(mLargeLabel, 1f);
            } else {
                LayoutParams iconParams = (LayoutParams) mIcon.getLayoutParams();
                iconParams.gravity = Gravity.CENTER;
                iconParams.topMargin = mDefaultMargin;
                mIcon.setLayoutParams(iconParams);
                mLargeLabel.setVisibility(INVISIBLE);
                ViewCompat.setScaleX(mLargeLabel, 0.5f);
                ViewCompat.setScaleY(mLargeLabel, 0.5f);
            }
            mSmallLabel.setVisibility(INVISIBLE);
        } else {
            if (checked) {
                LayoutParams iconParams = (LayoutParams) mIcon.getLayoutParams();
                iconParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
                iconParams.topMargin = mDefaultMargin + mShiftAmount;
                mIcon.setLayoutParams(iconParams);
                mLargeLabel.setVisibility(VISIBLE);
                mSmallLabel.setVisibility(INVISIBLE);

                ViewCompat.setScaleX(mLargeLabel, 1f);
                ViewCompat.setScaleY(mLargeLabel, 1f);
                ViewCompat.setScaleX(mSmallLabel, mScaleUpFactor);
                ViewCompat.setScaleY(mSmallLabel, mScaleUpFactor);
            } else {
                LayoutParams iconParams = (LayoutParams) mIcon.getLayoutParams();
                iconParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
                iconParams.topMargin = mDefaultMargin;
                mIcon.setLayoutParams(iconParams);
                mLargeLabel.setVisibility(INVISIBLE);
                mSmallLabel.setVisibility(VISIBLE);

                ViewCompat.setScaleX(mLargeLabel, mScaleDownFactor);
                ViewCompat.setScaleY(mLargeLabel, mScaleDownFactor);
                ViewCompat.setScaleX(mSmallLabel, 1f);
                ViewCompat.setScaleY(mSmallLabel, 1f);
            }
        }

啊哈。看了这么多终于找到原因了。 这就是问题所在。我们见到如果我们吧mShiftingMode设置为false那么就不会出现那种效果。怎么设置呢。我们可以使用反射的机制来进行设置。
代码如下

 public static void disableShiftMode(BottomNavigationView view) {
        BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
        try {
            Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
            shiftingMode.setAccessible(true);
            shiftingMode.setBoolean(menuView, false);
            shiftingMode.setAccessible(false);
            for (int i = 0; i < menuView.getChildCount(); i++) {
                BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
                item.setShiftingMode(false);
                item.setChecked(item.getItemData().isChecked());
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

clipboard.png


http://www.niftyadmin.cn/n/1843956.html

相关文章

POJ 2769 Reduced ID Numbers

传送门&#xff1a;http://poj.org/problem?id2769 就是让你计算一个最小的数&#xff0c;使得n个数对这个数取某模的值都不一样 比暴力好的一点是利用了mark数组可以降低复杂度 #include <iostream> #include <cstring> #include <cstdio> using namespa…

logistic回归简介

logistic回归 一、名词解释&#xff1a; logistic回归又称罗杰斯蒂克回归分析&#xff0c;或逻辑回归分析。 Logistic回归为概率型非线性回归模型&#xff0c;是研究分类观察结果y与一些影响因素x&#xff08;单变量&#xff0c;多变量都可以&#xff09;之间关系的一种多变…

2 MITK测试代码step4

1 官网教程 http://docs.mitk.org/2016.11/Step04Page.html 2 Step4.cpp /*The Medical Imaging Interaction Toolkit (MITK)Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved.This software is distrib…

网络流_最大流_POJ 3281

题目链接&#xff1a;http://poj.org/problem?id3281 个人认为这个题的难点就在于见图&#xff0c;应为有多个源点和起点&#xff0c;所以我们可以设置一个超级源点和超级汇点 将牛分1为2&#xff0c;一个牛吃菜&#xff0c;一个牛吃草&#xff0c;两个牛之间一一对应&#…

1 java环境配置记录

1.选择哪个版本 http://blog.csdn.net/liujun13579/article/details/7684604 2.安装jdk http://www.oracle.com/technetwork/cn/java/javase/downloads/index.html 一定选择与下面eclipse位数相同的&#xff0c;不然会报错 然后配置环境变量 http://jingyan.baidu.com/ar…

SparseAutoEncoder 稀疏编码详解(Andrew ng课程系列)

先简单叙述问题&#xff0c;源码详细解析在下面 前言 首先介绍sparse autoencoder的一个实例练习&#xff0c;参考Ng的网页教程&#xff1a;Exercise:Sparse Autoencoder。这个例子所要实现的内容大概如下&#xff1a;从给定的很多张自然图片中截取出大小为8*8的小patc…

2 jni使用测试

1 JNI编程指南一书翻译(含介绍) http://www.kancloud.cn/owenoranba/jni 代码文件&#xff1a; https://github.com/leeowenowen/jni-examples 2 JNI_最简单的Java调用C/C代码 http://blog.csdn.net/wwj_748/article/details/28136061 3 注意事项 javah的使用的时候&…

Softmax回归代码详解

简介 Sfotmax回归分析是logistic回归分析在多个分类问题上面的发展。 Logistic回归中&#xff0c;训练集由m个标签样本组合构成&#xff1a; 对于给定的测试输入 &#xff0c;我们想用假设函数针对每一个类别j估算出概率值 p&#xff08;yj|x&#xff09;。也就是说&#…

4 jni opencv的使用

为啥直接都可以&#xff01; root52acd6c79e97:/home/huxiang_j/work/jni/jni_opencv# g -I$JAVA_HOME/include/ -I$JAVA_HOME/include/linux -shared -fPIC -o libmyjni.so source.cpp source.cpp: In function _jstring* Java_jniOpencv_jniCanny(JNIEnv*, jobject, jstring…

4 linux 下jni opencv的使用

1 编译安装opencv http://blog.csdn.net/qq_16949707/article/details/54602091 2 编写java文 public class jniOpencv{public native void sayHello();public native String jniCanny(String src); // public native void setInt(String src);public static void main(St…

SVD奇异值分解:主成分分析的矩阵论解释

SVD分解 SVD分解是LSA的数学基础&#xff0c;本文是我的LSA学习笔记的一部分&#xff0c;之所以单独拿出来&#xff0c;是因为SVD可以说是LSA的基础&#xff0c;要理解LSA必须了解SVD&#xff0c;因此将LSA笔记的SVD一节单独作为一篇文章。本节讨论SVD分解相关数学问题&#xf…

HDU_1114_背包问题

题意就是&#xff1a;给你一定的空间&#xff0c;一定种类的硬币&#xff0c;每种硬币可以重复使用多次&#xff0c;让我们计算消耗这么多的空间的最小质量 dp[i1][j]表示的就是从前i种硬币中挑选质量小于j的最小价值 转移方程&#xff1a; dp[i1][j] min(dp[i][j],dp[i1][…

5 linux jni 调用dcmtk

1 安装dcmtk https://github.com/commontk/DCMTK/blob/patched-DCMTK-3.6.1_20160216/INSTALL 比较坑的是这个装的是静态的库&#xff0c;折腾了我一天&#xff0c;你们也可以先试试&#xff0c;看怎么利用第三方静态库编译成.so&#xff0c;然后供jni调用&#xff0c;按道理…

HDU_2159_背包问题

Description 最近xhd正在玩一款叫做FATE的游戏&#xff0c;为了得到极品装备&#xff0c;xhd在不停的杀怪做任务。久而久之xhd开始对杀怪产生的厌恶感&#xff0c;但又不得不通过杀怪来升完这最后一级。现在的问题是&#xff0c;xhd升掉最后一级还需n的经验值&#xff0c;xhd还…

1 docker环境使用tensorflow以及jupyter notebook的使用

1 docker一些介绍 注&#xff08;92服务器上已经配置好docker&#xff0c;但是需要sudo命令才能运行&#xff09; 这俩篇文章介绍了docker大概是怎么玩的。 大白话Docker入门&#xff08;一&#xff09; https://www.atatech.org/articles/65782#6 大白话Docker入门&#…

一些安装记录

1 安装测试Lasagne git clone https://github.com/Lasagne/Lasagne.git cd Lasagne pip install -r requirements.txt pip install --editable . http://blog.csdn.net/taneijia/article/details/46452905 2 linux安装python-opencv http://stackoverflow.com/questions/40…
最新文章