置顶 小凡特爱写代码 已于 2022-03-31 00:46:49 修改 3929 收藏 22 分类专栏: MaterialDesign 文章标签: 底部导航栏 BottomNav 安卓库控件 版权 MaterialDesign 专栏收录该内容 5 篇文章0 订阅 订阅专栏 BottomNavigationView实现底部导航栏的整体效果如下图所示: BottomNavigationView 引入包最新 基本使用 app:menu="@menu/menu_navigation_fix"中的界面 控件点击时候颜色选择@color/sl_color_green_grey 完整的MainActivity代码 app:labelVisibilityMode=""属性 字体的style-可以设置字体大小 导航栏高度和文字和图片之间的间距 设置水波纹效果 app:itemRippleColor 切换自己设定选中图片和未选中图片 除去自带着色效果 创建一个drawable选择器 设置相应item中android:icon属性 添加一个消息提示红色点 第一种方式粗略的添加方式 第二种(消息红色的中心放在图片右上角顶点) 引入包最新 implementation 'com.google.android.material:material:1.2.0-alpha06' 1 基本使用 <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bottom_navigation_1" android:layout_width="match_parent" android:layout_height="wrap_content" app:itemBackground="@color/white" app:itemIconTint="@color/sl_color_green_grey" app:itemTextColor="@color/sl_color_green_grey" app:menu="@menu/menu_navigation_fix" /> 1 2 3 4 5 6 7 8 BottomNavigationView控件的主要属性含义: app:iteamBackground 指的是底部导航栏的背景颜色,默认是主题的颜色 app:itemIconTint 指的是底部导航栏中图片的颜色 app:itemTextColor 指的是底部导航栏文字的颜色 app:menu 指的是菜单布局(文字和图片都写在这个里面) app:menu="@menu/menu_navigation_fix"中的界面 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas./apk/res/android" xmlns:app="http://schemas./apk/res-auto"> <item android:id="@+id/action_message" android:checked="true" android:icon="@mipmap/icon_message" android:title="@string/message" /> <item android:id="@+id/action_find" android:icon="@mipmap/icon_find" android:title="@string/find" /> <item android:id="@+id/action_circle" android:icon="@mipmap/icon_circle" android:title="@string/circle" /> </menu> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 控件点击时候颜色选择@color/sl_color_green_grey <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas./apk/res/android"> <item android:color="#b8b9bd" android:state_checked="false" /> <item android:color="#0fbbbb" android:state_checked="true" /> </selector> 1 2 3 4 5 完整的MainActivity代码 public class MainActivity extends AppCompatActivity { private FrameLayout mainFrame; private BottomNavigationView bottomNavigation; private MyFragment messageFragment, findFragment, circleFragment; private Fragment[] fragments; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { messageFragment = new MyFragment(); messageFragment.setMessage(getResources().getString(R.string.message)); findFragment = new MyFragment(); findFragment.setMessage(getResources().getString(R.string.find)); circleFragment = new MyFragment(); circleFragment.setMessage(getResources().getString(R.string.circle)); fragments = new Fragment[]{messageFragment, findFragment, circleFragment}; mainFrame = findViewById(R.id.mainContainer); //设置fragment到布局 getSupportFragmentManager() .beginTransaction() .replace(R.id.mainContainer, messageFragment) .commit(); bottomNavigation = findViewById(R.id.navigation); //这里是bottomnavigationview的点击事件 bottomNavigation.setOnNavigationItemSelectedListener(listener); } private BottomNavigationView.OnNavigationItemSelectedListener listener = new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { int id = item.getItemId(); if (id == R.id.action_message) switchFragment(fragments[0]); else if (id == R.id.action_find) switchFragment(fragments[1]); else if (id == R.id.action_circle) switchFragment(fragments[2]); return true; } }; // 切换fragment private void switchFragment(Fragment fragment) { FragmentManager fm = getSupportFragmentManager(); FragmentTransaction transaction = fm.beginTransaction(); transaction.replace(R.id.mainContainer, fragment); transaction.commitAllowingStateLoss(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 运行的效果图如下: app:labelVisibilityMode=""属性 item多的时候,指的是item非选中状态显示文字,有以下几个值: labeled 图标文字都显示 selected auto unlabeled 文字不显示 它们依次运行如下图所示 auto和select和i 属性sShifting有关 此时isShifting=true;你会发现auto和 selected的效果是一样的效果; 当isShifting=false时候,auto和lable是一样的效果; 关键是这个isShift属性没法设置,目前只有设置2个item的时候它们才好区别;感觉auto这个属性有点鸡肋;下面贴一下关键的源码: switch (labelVisibilityMode) { case LabelVisibilityMode.LABEL_VISIBILITY_AUTO: if (isShifting) { if (checked) { setViewLayoutParams(icon, defaultMargin, Gravity.CENTER_HORIZONTAL | Gravity.TOP); setViewValues(largeLabel, 1f, 1f, VISIBLE); } else { setViewLayoutParams(icon, defaultMargin, Gravity.CENTER); setViewValues(largeLabel, 0.5f, 0.5f, INVISIBLE); } smallLabel.setVisibility(INVISIBLE); } else { if (checked) { setViewLayoutParams( icon, (int) (defaultMargin + shiftAmount), Gravity.CENTER_HORIZONTAL | Gravity.TOP); setViewValues(largeLabel, 1f, 1f, VISIBLE); setViewValues(smallLabel, scaleUpFactor, scaleUpFactor, INVISIBLE); } else { setViewLayoutParams(icon, defaultMargin, Gravity.CENTER_HORIZONTAL | Gravity.TOP); setViewValues(largeLabel, scaleDownFactor, scaleDownFactor, INVISIBLE); setViewValues(smallLabel, 1f, 1f, VISIBLE); } } break; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 字体的style-可以设置字体大小 app:itemTextAppearanceActive="@style/selectText"//选中字体大小风格, app:itemTextAppearanceInactive="@style/unSelectText"//未选中字体大小风格 1 2 <?xml version="1.0" encoding="utf-8"?> <resources> <style name="selectText"> <item name="android:textSize">20sp</item> <item name="android:drawablePadding">8dp</item> </style> <style name="unSelectText"> <item name="android:textSize">14sp</item> <item name="android:drawablePadding">4dp</item> </style> </resources> 1 2 3 4 5 6 7 8 9 10 11 12 13 导航栏高度和文字和图片之间的间距 <!-- 导航栏高度 --> <dimen name="design_bottom_navigation_height">80dp</dimen> 1 2 设置了这个之后导航栏高度就变高了,同时图片和文字之间的距离就变大了,具体是多少我也不清楚 其他的设置都是瞎搞; 设置水波纹效果 app:itemRippleColor 先说一下这里的 app:itemBackground 和app:itemRippleColor都是设置给到导航栏的背景 如果要设置水波纹有有效果,那么必须不设置背景: app:itemBackground="@null" app:itemRippleColor="@color/design_default_color_primary" 1 2 只有这样才会有效果;否则无效; 这是在其源码里面发现的: int itemBackground = a.getResourceId(R.styleable.BottomNavigationView_itemBackground, 0); if (itemBackground != 0) { menuView.setItemBackgroundRes(itemBackground); } else { ColorStateList itemRippleColor = MaterialResources.getColorStateList( context, a, R.styleable.BottomNavigationView_itemRippleColor); setItemRippleColor(itemRippleColor); } 1 2 3 4 5 6 7 8 9 再看看 setItemRippleColor(itemRippleColor);方法,最后还是把水波纹效果设置给了 menuView.setItemBackgroundRes(); public void setItemRippleColor(@Nullable ColorStateList itemRippleColor) { if (this.itemRippleColor == itemRippleColor) { // Clear the item background when setItemRippleColor(null) is called for consistency. if (itemRippleColor == null && menuView.getItemBackground() != null) { menuView.setItemBackground(null); } return; } this.itemRippleColor = itemRippleColor; if (itemRippleColor == null) { menuView.setItemBackground(null); } else { ColorStateList rippleDrawableColor = RippleUtils.convertToRippleDrawableColor(itemRippleColor); if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { menuView.setItemBackground(new RippleDrawable(rippleDrawableColor, null, null)); } else { GradientDrawable rippleDrawable = new GradientDrawable(); // TODO: Find a workaround for this. Currently on certain devices/versions, LayerDrawable // will draw a black background underneath any layer with a non-opaque color, // (e.g. ripple) unless we set the shape to be something that's not a perfect rectangle. rippleDrawable.setCornerRadius(0.00001F); Drawable rippleDrawableCompat = DrawableCompat.wrap(rippleDrawable); DrawableCompat.setTintList(rippleDrawableCompat, rippleDrawableColor); menuView.setItemBackground(rippleDrawableCompat); } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 切换自己设定选中图片和未选中图片 想要切换自己UI设计师给的两种不同的Ui图片; 除去自带着色效果 navigation.setItemIconTintList(null) 除去自带着色效果 (在XML中app:itemIconTint=@null无效,需要代码设置) 创建一个drawable选择器 有几个item就创建几个,比如sl_drawable_circle.xml <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas./apk/res/android"> <item android:state_checked="false" android:drawable="@mipmap/icon_circle"/> <item android:state_checked="true" android:drawable="@mipmap/icon_circle_focus"/> </selector> 1 2 3 4 5 设置相应item中android:icon属性 找到相应item中 android:icon属性 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas./apk/res/android" xmlns:app="http://schemas./apk/res-auto"> <item android:id="@+id/action_circle" android:icon="@drawable/sl_drawable_circle" android:title="@string/circle" /> </menu> 1 2 3 4 5 6 7 8 第二个中的切换都是原始图片的切换; 以上就是总结的全部内容了;欢迎评论和点赞,交流,互相学习了! 添加一个消息提示红色点 第一种方式粗略的添加方式 //获取整个的NavigationView BottomNavigationMenuView menuView = (BottomNavigationMenuView) navigation.getChildAt(0); //这里就是获取所添加的每一个Tab(或者叫menu), View tab = menuView.getChildAt(0); BottomNavigationItemView itemView = (BottomNavigationItemView) tab; //加载我们的角标View,新创建的一个布局 View badge = LayoutInflater.from(this).inflate(R.layout.item_red_dot, menuView, false); //添加到Tab上 FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(badge.getLayoutParams()); lp.gravity = Gravity.TOP | Gravity.END; itemView.addView(badge, lp); 1 2 3 4 5 6 7 8 9 10 11 第二种(消息红色的中心放在图片右上角顶点) //添加消息红点第二种方式 BottomNavigationMenuView menuView = (BottomNavigationMenuView) navigation.getChildAt(0); View tab = menuView.getChildAt(0); BottomNavigationItemView itemView = (BottomNavigationItemView) tab; //从系统里面获取图标的ImageView ImageView iv = itemView.findViewById(R.id.icon); //加载我们的角标View,新创建的一个布局 final View badge = LayoutInflater.from(this).inflate(R.layout.item_red_dot, menuView, false); final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(badge.getLayoutParams()); //等到有高度以后在布局 iv.post(new Runnable() { @Override public void run() { lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; lp.topMargin = iv.getTop() - lp.height / 2;//图片top - 消息点的高度一半 lp.leftMargin = iv.getWidth() / 2;//图片的宽度的一半 itemView.addView(badge, lp); } }); ———————————————— 版权声明:本文为CSDN博主「小凡特爱写代码」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/eyishion/article/details/112688387 |
|