BottomNavigationView有兩種動畫:
1. 超過3個時的圖片,非選中狀態,會隱藏文字標題,且將圖片居中,造成圖片偏移的效果。原始碼中判斷是否可以偏移:
private boolean isShifting(@LabelVisibilityMode int labelVisibilityMode, int childCount) {
return labelVisibilityMode == LabelVisibilityMode.LABEL_VISIBILITY_AUTO
? childCount > 3
: labelVisibilityMode == LabelVisibilityMode.LABEL_VISIBILITY_SELECTED;
}
複製程式碼
所以再xml中設定labelVisibilityMode為labeled來禁止這個動效
app:labelVisibilityMode="labeled"
複製程式碼
2. 選中和非選中狀態變化時的動畫
BottomNavigationItemView有兩個標題的TextView:smallLabel和largeLabel。且在設定某一項選中時會修改樣式:
@Override
public void setChecked(boolean checked) {
largeLabel.setPivotX(largeLabel.getWidth() / 2);
largeLabel.setPivotY(largeLabel.getBaseline());
smallLabel.setPivotX(smallLabel.getWidth() / 2);
smallLabel.setPivotY(smallLabel.getBaseline());
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;
case LabelVisibilityMode.LABEL_VISIBILITY_SELECTED:
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);
break;
case LabelVisibilityMode.LABEL_VISIBILITY_LABELED:
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;
case LabelVisibilityMode.LABEL_VISIBILITY_UNLABELED:
setViewLayoutParams(icon, defaultMargin, Gravity.CENTER);
largeLabel.setVisibility(GONE);
smallLabel.setVisibility(GONE);
break;
default:
break;
}
複製程式碼
所以當labelVisibilityMode是labeled時,會改變largeLabel的大小,係數scaleDownFactor是smallLabel和largeLabel的字型大小比值(可見calculateTextScaleFactors()方法)。
修改這個文字變大和變小的動效:
設定itemTextAppearanceActive和itemTextAppearanceInactive,將smallLabel和largeLabel的字型大小設定一樣
設定方法:
app:itemTextAppearanceActive="@style/navigation_tab_active"
app:itemTextAppearanceInactive="@style/navigation_tab_inactive"
複製程式碼
樣式:styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="navigation_tab_inactive">
<item name="android:textSize">12sp</item>
</style>
<style name="navigation_tab_active">
<item name="android:textSize">12sp</item>
</style>
</resources>
複製程式碼
原始碼:
public void setTextAppearanceInactive(@StyleRes int inactiveTextAppearance) {
TextViewCompat.setTextAppearance(smallLabel, inactiveTextAppearance);
calculateTextScaleFactors(smallLabel.getTextSize(), largeLabel.getTextSize());
}
public void setTextAppearanceActive(@StyleRes int activeTextAppearance) {
TextViewCompat.setTextAppearance(largeLabel, activeTextAppearance);
calculateTextScaleFactors(smallLabel.getTextSize(), largeLabel.getTextSize());
}
複製程式碼