前提
- アイコンが4個
- support library 28 rc01の話
- 27の場合は BottomNavigationViewをカスタマイズして使う でよさそう
どうやる
これで、ラベルが常に表示される。やったね!
<android.support.design.widget.BottomNavigationView ... app:labelVisibilityMode="labeled" ...>
以下の内容は、動作しますが適切とは言えません。
@SuppressLint("RestrictedApi") private fun disableBottomNavigationShiftMode() { val menuView = navigation.getChildAt(0) as BottomNavigationMenuView for (i in 0 until menuView.childCount) { val item = menuView.getChildAt(i) as BottomNavigationItemView item.setShifting(false) } menuView.labelVisibilityMode = 1 }
@SuppressLint("RestrictedApi")
する必要がありヤダな〜というのが本音だけどまあしょうがない
考えたこと
BottomNavigationItemViewにsetShifting
というメソッドがあるので、それをfalseに指定する。
これだけだとタブを切り替えたときにタイトルが消えてしまうため、BottomNavigationMenuViewのprivate APIである isShifting
が falseを返すようにする必要がある。
(タブを切り替えるたび、BottomNavigationMenuViewのupdateMenuViewメソッドでViewの更新が行われている)
isShifting
は以下のようなロジックであるので、menuView.labelVisibilityMode = 1
と指定するとfalseを返すようになる
private boolean isShifting(int labelVisibilityMode, int childCount) { return labelVisibilityMode == -1 ? childCount > 3 : labelVisibilityMode == 0; }
ちなみに 1 ではなく 100 とかを指定しても多分動くんだけど、 BottomNavigationItemViewのsetChecked
でlabelVisibilityMode
が使われているので変な値を入れるのは避けたほうがよいと思う。
setViewValues の最後の引数が 0, 4, 8 となっているが、これは View.VISIBLE
と対応していて、0はVISIBLE, 4はINVISIBLE, 8はGONEとなる。
定数を使わない理由はよくわからない。
public void setChecked(boolean checked) { // 略 switch(this.labelVisibilityMode) { case -1: if (this.isShifting) { if (checked) { this.setViewLayoutParams(this.icon, this.defaultMargin, 49); this.setViewValues(this.largeLabel, 1.0F, 1.0F, 0); } else { this.setViewLayoutParams(this.icon, this.defaultMargin, 17); this.setViewValues(this.largeLabel, 0.5F, 0.5F, 4); } this.smallLabel.setVisibility(4); } else if (checked) { this.setViewLayoutParams(this.icon, (int)((float)this.defaultMargin + this.shiftAmount), 49); this.setViewValues(this.largeLabel, 1.0F, 1.0F, 0); this.setViewValues(this.smallLabel, this.scaleUpFactor, this.scaleUpFactor, 4); } else { this.setViewLayoutParams(this.icon, this.defaultMargin, 49); this.setViewValues(this.largeLabel, this.scaleDownFactor, this.scaleDownFactor, 4); this.setViewValues(this.smallLabel, 1.0F, 1.0F, 0); } break; case 0: if (checked) { this.setViewLayoutParams(this.icon, this.defaultMargin, 49); this.setViewValues(this.largeLabel, 1.0F, 1.0F, 0); } else { this.setViewLayoutParams(this.icon, this.defaultMargin, 17); this.setViewValues(this.largeLabel, 0.5F, 0.5F, 4); } this.smallLabel.setVisibility(4); break; case 1: if (checked) { this.setViewLayoutParams(this.icon, (int)((float)this.defaultMargin + this.shiftAmount), 49); this.setViewValues(this.largeLabel, 1.0F, 1.0F, 0); this.setViewValues(this.smallLabel, this.scaleUpFactor, this.scaleUpFactor, 4); } else { this.setViewLayoutParams(this.icon, this.defaultMargin, 49); this.setViewValues(this.largeLabel, this.scaleDownFactor, this.scaleDownFactor, 4); this.setViewValues(this.smallLabel, 1.0F, 1.0F, 0); } break; case 2: this.setViewLayoutParams(this.icon, this.defaultMargin, 17); this.largeLabel.setVisibility(8); this.smallLabel.setVisibility(8); } // 略 }