基本使用应该基本都会,我是基于最新的工程环境来搞的,这两天过程中遇到一些问题。比如按照网上一些资料,
1. 去掉水波纹
实际我发现没有效果。然后我跟踪了一下源码设置水波纹的地方:
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);
}
我发现当你不设置这个的时候或者设置为null的时候,其实还会去找R.styleable.BottomNavigationView_itemRippleColor。 怎么感觉跟其他人说的不一样,难道是我理解错了?
于是我重新了Style里面的**itemRippleColor为null **- 其他属性也一并贴出
<!-- BottomNavigationView属性-->
<style name="BottomNavigationViewTheme" parent="Widget.MaterialComponents.BottomNavigationView">
<!--波纹颜色无-->
<item name="itemRippleColor">@null</item>
<item name="itemTextAppearanceActive">@style/BottomNavigationViewTheme.TextAppearance_Selected
</item>
<item name="itemTextAppearanceInactive">@style/BottomNavigationViewTheme.TextAppearance
</item>
</style>
<!-- BottomNavigationView 字体属性-->
<style name="BottomNavigationViewTheme.TextAppearance" parent="TextAppearance.MaterialComponents.Caption">
<item name="android:textSize">14sp</item>
</style>
<style name="BottomNavigationViewTheme.TextAppearance_Selected" parent="TextAppearance.MaterialComponents.Caption">
<item name="android:textSize">16sp</item>
</style>
然后设置一把:可以啦。。没有水波纹啦。。头大。。
<!-- 底部导航栏BottomNavigationView-->
<!-- BottomNavigationView-->
<!-- app:itemBackground="@null"无效 用app:itemRippleColor="@null"-->
<!-- app:itemIconSize="14dp"-->
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/ahb_bottomBNv"
style="@style/BottomNavigationViewTheme"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/tablayout_bg_shape"
app:itemHorizontalTranslationEnabled="false"
app:itemTextColor="@drawable/bottom_text_selector"
app:labelVisibilityMode="labeled"
app:layout_constraintBottom_toBottomOf="parent">
</com.google.android.material.bottomnavigation.BottomNavigationView>
**2. **调整导航栏高度,以及图片文字间距,同时额外设置图片距离顶部一定高度,腾出空间放角标
2.1我们要清楚design_bottom_navigation_margin是设置图片和文字的间距,但是底部导航栏默认高度是56dp,所以你如果设置间距了margin,那么你的高度design_bottom_navigation_height请相应的margin,不然会重叠的。。
2.2 其次design_bottom_navigation_icon_size 这个是可以调整图标尺寸,同样比如你大小为60dp,你的design_bottom_navigation_height也需要增加** 60dp- 24dp,**因为图标默认是24,你相当于额外增加了高度,为了完整显示,请增加BottomNavigationView高度。 所以dimens覆写几个属性。。
<resources>
<!-- 修改文字和图片的间距-->
<dimen name="design_bottom_navigation_margin">4dp</dimen>
<dimen name="design_bottom_navigation_icon_size">44dp</dimen>
<!-- 选中时的最大宽度-->
<!-- <dimen name="design_bottom_navigation_active_item_max_width">168dp</dimen>-->
<!-- 未选中的最大宽度-->
<!-- <dimen name="design_bottom_navigation_item_max_width">168dp</dimen>-->
<!-- 高度 默认的底部导航栏的高度是 56dp,我们增加间距4dp=60dp-->
<dimen name="design_bottom_navigation_height">95dp</dimen>
</resources>
3. 注意,注意!针对2.2提到的属性重写,其中我们要注意design_bottom_navigation_margin,当我们设置高度比较高时,如果此时**design_bottom_navigation_margin还是4dp,那么结果是:你会发现图片和文字分离了,中间空了一定的高度。。
此时我们要增加design_bottom_navigation_margin的高度,相当于增加了icon距离顶部的间距,看源码:从下往下大概跟一下》。。。
最后我们发现其实当你ahbBottomBNv.getMenu().getItem(position).setChecked(true);的时候,就会设置相关属性。 这个时候已经设置了icon的topMargin。。所以我们增加下design_bottom_navigation_margin即可。。 像网上描述的这个margin属性是图片和文字的间距,从目前粗浅的观摩源码来看是不改变默认属性的情况下是有效的。如果有更深入的理解,麻烦指教一下,谢谢。
**4。 **关于如何动态修改底部图标,采用动态从网络获取的方式,提供工具类就好了:
BottomNavigationViewHelper.java
package com.hl.base_module.util.bottomnavigation;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.google.android.material.bottomnavigation.BottomNavigationItemView;
import com.google.android.material.bottomnavigation.BottomNavigationMenuView;
import com.google.android.material.bottomnavigation.BottomNavigationView;
public class BottomNavigationViewHelper {
/**
* 设置图片尺寸
*
* @param view
* @param width
* @param height
*/
public static void setImageSize(BottomNavigationView view, int width, int height) {
BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
try {
for (int i = 0; i < menuView.getChildCount(); i++) {
BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
ImageView imageView = item.findViewById(com.google.android.material.R.id.icon);
final ViewGroup.LayoutParams layoutParams = imageView.getLayoutParams();
layoutParams.height = width;
layoutParams.width = height;
imageView.setLayoutParams(layoutParams);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 设置Icon距离顶部高度
* 不需要了,直接设置design_bottom_navigation_margin属性即可
*
* @param view
* @param marginTop
*/
public static void setImageMarginTop(BottomNavigationView view, int marginTop) {
BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
try {
for (int i = 0; i < menuView.getChildCount(); i++) {
BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
ImageView imageView = item.findViewById(com.google.android.material.R.id.icon);
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) imageView.getLayoutParams();
layoutParams.topMargin = marginTop;
imageView.setLayoutParams(layoutParams);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 设置Icon为网络图标
*
* @param view
* @param imgUrl
*/
public static void replaceItemImage(BottomNavigationView view, String[] imgUrl) {
BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
try {
for (int i = 0; i < menuView.getChildCount(); i++) {
BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
ImageView imageView = item.findViewById(com.google.android.material.R.id.icon);
Glide.with(view.getContext())
.load(imgUrl[i])
.into(imageView);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 设置Icon为刷新图标
*
* @param view
* @param gifUrl
*/
public static void replaceRefreshImage(BottomNavigationView view, int index, String gifUrl) {
BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
try {
BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(index);
ImageView imageView = item.findViewById(com.google.android.material.R.id.icon);
Glide.with(view.getContext())
.load(gifUrl)
.into(imageView);
} catch (Exception e) {
e.printStackTrace();
}
}
}
**4.1 **使用:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// 可以模拟请求成功后加载网络图标
BottomNavigationViewHelper.replaceItemImage(getViewDataBinding().ahbBottomBNv,
new String[]{"https://file01.16sucai.com/d/file/2012/1023/20121023075322560.png",
"https://file01.16sucai.com/d/file/2012/1023/20121023075322530.png"});
}
}, 5000);
4.2.1 还可以点击实现刷新图片,刷新结束后回归正常图片 - 加载一个gif
// 底部菜单再次点击事件回调 - 这里我们可以做转圈刷新当前页面的效果
getViewDataBinding().ahbBottomBNv.setOnNavigationItemReselectedListener(new BottomNavigationView.OnNavigationItemReselectedListener() {
@Override
public void onNavigationItemReselected(@NonNull MenuItem item) {
// 再次点击首页,通知首页进行刷新
EventBus.getDefault().post(new MessageEvent("再次点击刷新", "update_home"));
BottomNavigationViewHelper.replaceRefreshImage(getViewDataBinding().ahbBottomBNv, 0, "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1589021367118&di=06f571cc13c0aca8f6b4afe85a328b24&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20170914%2F6e33a4c4ff5d4ce2b6ce0cd8523c3733.gif");
}
});
**4.2.2 **等刷新结束后,重新加载一个原来的图标即可 - 我用Eventbus做的通知哈。。可以其他方式
/**
* 收到刷新
* @param messageEvent
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void updateRefreshFinish(MessageEvent messageEvent) {
if (messageEvent.getObject().equals("update_home_finish")) {
BottomNavigationViewHelper.replaceRefreshImage(getViewDataBinding().ahbBottomBNv, 0, "https://file01.16sucai.com/d/file/2012/1023/20121023075322560.png");
}
}
基本上差不多了。总体效果
工程地址(对了角标就是自定义了一个Textview,在librarys/lib_miniui模块下面):https://github.com/FanChael/MVVM 欢迎一起学习讨论指教,谢谢star...我是打算继续完善,未来用来做模板工程。太多细节要处理了。另外很多类似商场首页效果还没来得及搞。。