移除 BottomNavigationView 标签

106

谷歌发布了新的支持库v25,其中包含BottomNavigationView。

输入图像描述

是否有任何方法可以移除选项卡上的标签?


1
你尝试过从菜单<item>中删除标题吗? - Mike M.
9
移除图标标题后,图标下方会有额外的内边距。添加 layout_marginBottom="-16dp" 可以移除此内边距,但也会使所有视图变小。 - dzikovskyy
你可以设置自定义高度并在顶部添加一些额外的padding,代替设置margin。这样可以让图标居中显示。 - Bolling
5
我只是这样修复它: android:paddingTop="8dp" android:layout_marginBottom="-8dp"这可以防止该条变得更小。 - Palm
8个回答

277

希望我来得不算太晚。

但从Design Support Library 28.0.0-alpha1开始,您可以使用该属性。

app:labelVisibilityMode="unlabeled"

未标记的BottomNavigationView

你也可以使用其他值,如“自动”,“带标签”和“已选择”。


使用哪个支持库?v7还是Design? - Sagar Maiyad
设计支持库 28.0.0 - Abdul-Aziz-Niazi
1
你是在哪个类中编写这个代码的? - Explorex
1
@Explorex 这是安卓的底部导航视图,我提到的属性是该类中使用的xml属性,用于该视图的xml标签。你也可以在代码中使用它 https://developer.android.com/reference/com/google/android/material/bottomnavigation/LabelVisibilityMode - Abdul-Aziz-Niazi
我们可以改变文本和图标的位置吗?我希望文本在图标旁边。 - undefined

22

我不喜欢这个库。当单击时,它会改变图标位置,而且没有办法使图标位置在单击时固定。 - Dika

18

很不幸,BottomNavigationView的第一个版本存在许多限制。目前,您无法仅使用支持设计API删除标题。因此,在谷歌实现它之前解决这个限制,您可以使用反射执行以下操作:

1. 在bottom_navigation_menu.xml文件中将标题设置为空。

2. 扩展BottomNavigationView:

    public class MyBottomNavigationView extends BottomNavigationView {

      public MyBottomNavigationView(Context context, AttributeSet attrs) {
          super(context, attrs);
          centerMenuIcon();
      }

      private void centerMenuIcon() {
          BottomNavigationMenuView menuView = getBottomMenuView();

          if (menuView != null) {
              for (int i = 0; i < menuView.getChildCount(); i++) {
                BottomNavigationItemView menuItemView = (BottomNavigationItemView) menuView.getChildAt(i);

                AppCompatImageView icon = (AppCompatImageView) menuItemView.getChildAt(0);

                FrameLayout.LayoutParams params = (LayoutParams) icon.getLayoutParams();
                params.gravity = Gravity.CENTER;

                menuItemView.setShiftingMode(true);
              }
          }
      }

      private BottomNavigationMenuView getBottomMenuView() {
          Object menuView = null;
          try {
              Field field = BottomNavigationView.class.getDeclaredField("mMenuView");
              field.setAccessible(true);
              menuView = field.get(this);
          } catch (NoSuchFieldException | IllegalAccessException e) {
              e.printStackTrace();
          }

          return (BottomNavigationMenuView) menuView;
      }
    }

3. 将这个自定义视图添加到layout.xml中

更多细节可以查看我在Github上实现的示例代码


不需要使用反射,您可以通过使用菜单项ID调用findViewById()来获取每个BottomNavigationItemView(就像@NikolaDespotoski在他的答案中所做的那样)。 - Fred Porciúncula
1
现在他们支持移除标签 app:labelVisibilityMode="unlabeled" - Amjad Alwareh

12

1.menu/abc.xml中设置android:title="";

2. 创建以下使用反射的辅助类

import android.support.design.internal.BottomNavigationMenuView;
import android.support.design.widget.BottomNavigationView;
import android.support.v7.widget.AppCompatImageView;
import android.util.Log;
import android.view.Gravity;
import android.widget.FrameLayout;

import java.lang.reflect.Field;

public class BottomNavigationViewHelper {
    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);
                //noinspection RestrictedApi
                item.setShiftingMode(false);
                item.setPadding(0, 15, 0, 0);
                // set once again checked value, so view will be updated
                //noinspection RestrictedApi
                item.setChecked(item.getItemData().isChecked());
            }
        } catch (NoSuchFieldException e) {
            Log.e("BNVHelper", "Unable to get shift mode field", e);
        } catch (IllegalAccessException e) {
            Log.e("BNVHelper", "Unable to change value of shift mode", e);
        }
    }
} 

3. 在你的主活动中,添加以下行:

mBottomNav = (BottomNavigationView) findViewById(R.id.navigation);
BottomNavigationViewHelper.disableShiftMode(mBottomNav);

11

无反射方法:

private void removeTextLabel(@NonNull BottomNavigationView bottomNavigationView, @IdRes int menuItemId) {
    View view = bottomNavigationView.findViewById(menuItemId);
    if (view == null) return;
    if (view instanceof MenuView.ItemView) {
        ViewGroup viewGroup = (ViewGroup) view;
        int padding = 0;
        for (int i = 0; i < viewGroup.getChildCount(); i++) {
            View v = viewGroup.getChildAt(i);
            if (v instanceof ViewGroup) {
                padding = v.getHeight();
                viewGroup.removeViewAt(i);
            }
        }
        viewGroup.setPadding(view.getPaddingLeft(), (viewGroup.getPaddingTop() + padding) / 2, view.getPaddingRight(), view.getPaddingBottom());
    }
}

1
如果我想删除图标而不是文本,该怎么办? - Merhawi Fissehaye
我该如何在默认的BottomNavigation代码已经存在的主活动中调用它?@NikolaDespotoski - TiagoIB
@TiagoIB 只需将该方法设为静态并移至其他类中。或者将其保持为私有,并使用指定的参数进行调用。 - Nikola Despotoski
不好意思,但是我该如何将它插入到我的代码中?http://prntscr.com/he03j7 @NikolaDespotoski - TiagoIB

5
这只是一个临时解决方案。只需添加:app:itemTextColor="@android:color/transparent",这将使它呈现禁用状态与背景颜色相同。它确实使图标看起来更突出。

2

我想要去掉底部导航栏的 移动动画 和标签,但这里的解决方案都不太适用于我,所以我根据在这里学到的一切制作了自己的解决方案:

public void removeLabels(@IdRes int... menuItemIds) {
    getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override public boolean onPreDraw() {
            getViewTreeObserver().removeOnPreDrawListener(this);

            // this only needs to be calculated once for an unchecked item, it'll be the same value for all items
            ViewGroup uncheckedItem = findFirstUncheckedItem(menuItemIds);
            View icon = uncheckedItem.getChildAt(0);
            int iconTopMargin = ((LayoutParams) uncheckedItem.getChildAt(0).getLayoutParams()).topMargin;
            int desiredTopMargin = (uncheckedItem.getHeight() - uncheckedItem.getChildAt(0).getHeight()) / 2;
            int itemTopPadding = desiredTopMargin - iconTopMargin;

            for (int id : menuItemIds) {
                ViewGroup item = findViewById(id);
                // remove the label
                item.removeViewAt(1);
                // and then center the icon
                item.setPadding(item.getPaddingLeft(), itemTopPadding, item.getPaddingRight(),
                        item.getPaddingBottom());
            }

            return true;
        }
    });
}

@SuppressLint("RestrictedApi")
private ViewGroup findFirstUncheckedItem(@IdRes int... menuItemIds) {
    BottomNavigationItemView item = findViewById(menuItemIds[0]);
    int i = 1;
    while (item.getItemData().isChecked()) {
        item = findViewById(menuItemIds[i++]);
    }
    return item;
}

只需将此方法添加到您的自定义BottomNavigationView中,并传递菜单项的ID即可。

1
我建议你自己实现,可以参考sanf0rd的回答。但是AppCompatImageView对我来说不起作用。我将它改为了ImageView。并将getChildAt改为findViewById
另外,我隐藏了所有未选择项目的标签。
private void centerMenuIcon() {
    BottomNavigationMenuView menuView = getBottomMenuView();
    if (menuView != null) {
        for (int i = 0; i < menuView.getChildCount(); i++) {
            BottomNavigationItemView menuItemView = (BottomNavigationItemView) menuView.getChildAt(i);
            TextView smallText = (TextView) menuItemView.findViewById(R.id.smallLabel);
            smallText.setVisibility(View.INVISIBLE);
            //TextView largeText = (TextView) menuItemView.findViewById(R.id.largeLabel);
            ImageView icon = (ImageView) menuItemView.findViewById(R.id.icon);
            FrameLayout.LayoutParams params = (LayoutParams) icon.getLayoutParams();
            params.gravity = Gravity.CENTER;
            menuItemView.setShiftingMode(true);
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接