在查看
lottie
动画库的代码时发现它的底部是利用BottomNavigationView
实现的底部导航栏,但是却不受3个的限制(控件超过三个就会进行处理,隐藏除选中外的文字并缩小),还保留了控件原本3个以内的效果,这里我就把它的代码贴出来
BottomNavigationView
的结构,清楚了控件的构成就容易解决问题了
//从上倒下包含BottomNavigationView BottomNavigationMenu BottomNavigationItemView 复制代码
lottie
中代码使用kotlin
写的
private val TAG = NoShiftBottomNavigationView::class.java.nameclass NoShiftBottomNavigationView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : BottomNavigationView(context, attrs, defStyleAttr) { override fun onViewAdded(child: View?) { super.onViewAdded(child) removeShiftAnimation() } @SuppressLint("RestrictedApi") private fun removeShiftAnimation() { val menuView = getChildAt(0) as BottomNavigationMenuView try { menuView::class.java.getDeclaredField("mShiftingMode").apply { isAccessible = true setBoolean(menuView, false) isAccessible = false } menuView.children .map { it as BottomNavigationItemView } .forEach { it.setShiftingMode(false) it.setChecked(it.itemData.isChecked) } } catch (e: NoSuchFieldException) { Log.e(TAG, "Unable to get shift mode field", e) } catch (e: IllegalAccessException) { Log.e(TAG, "Unable to change value of shift mode", e) } }}复制代码
我也写了一份
java
的(最近正好在学koltin
)
public class NoShiftBottomNavigationView extends BottomNavigationView { private String TAG = getClass().getSimpleName(); public NoShiftBottomNavigationView(Context context) { this(context,null); } public NoShiftBottomNavigationView(Context context, AttributeSet attrs) { super(context, attrs,0); } public NoShiftBottomNavigationView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public void onViewAdded(View child) { super.onViewAdded(child); //当底部导航菜单被添加,去除系统的效果 removeShiftAnimation(); } @SuppressLint("RestrictedApi") private void removeShiftAnimation() { BottomNavigationMenuView menuView = (BottomNavigationMenuView) getChildAt(0); try { //利用反射获取到mShiftingMode属性,设置为false不需要shift动画效果(控制移动动画) Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode"); //忽略该属性的访问显示 shiftingMode.setAccessible(true); shiftingMode.setBoolean(menuView,false); shiftingMode.setAccessible(false); //取消每一个子菜单的shift动画效果(控制文字是否显示隐藏) for (int i = 0; i < menuView.getChildCount(); i++) { BottomNavigationItemView itemView = (BottomNavigationItemView) menuView.getChildAt(i); itemView.setShiftingMode(false); itemView.setChecked(itemView.getItemData().isChecked()); } } catch (NoSuchFieldException e) { Log.e(TAG, "Unable to get shift mode field", e); } catch (IllegalAccessException e) { Log.e(TAG, "Unable to change value of shift mode", e); } }}复制代码
注意
如果混淆了design包记得忽略混淆该属性,防止混淆后属性名变化,反射无法找到该属性,导致异常
-keepclassmembers class android.support.design.internal.BottomNavigationMenuView { boolean mShiftingMode; }复制代码