BottomNavigationView
のデザインが気に入ったので、単純なボタンを使用するのではなく、アプリに新しいメニューを実装することにしました。
ガイドラインとして this の投稿を採用しました。
BottomNavigationView
の- documentation によると、その目的は
アプリのトップレベルビュー間をすばやく移動できます。それは主にモバイルで使用するために設計されています。
私の場合、各MenuItem
にアクティビティを起動させたいだけですが、デフォルトでは常に1つのMenuItem
が選択されています。
私は色を白に設定しようとしました:
app:itemIconTint="@color/white"
app:itemTextColor="@color/white"
それでも、目に見えるように選択されたMenuItem
は他のものとは異なり(タイトルサイズが大きく)、それでも私は悩まされています。
非表示のMenuItem
を配置して次のように選択するというアイデアが思い付きました。
<item
Android:id="@+id/uncheckedItem"
Android:title="" />
そしてそのビューをGONE
にします:
bottomNavigationView.getMenu().findItem(R.id.uncheckedItem).setChecked(true);
bottomNavigationView.findViewById(R.id.uncheckedItem).setVisibility(View.GONE);
これにより、すべてのMenuItemsがオフになりますが、4番目のBottomNavigationView
がMenuItem
に落ち着いても、表示するMenuItemsが3つ以上あるため、デフォルトでGONE
はTitlesを非表示にします。
だから私の質問は残っています、すべてのMenuItemの選択を解除してそのタイトルを表示したままにするための離れた場所/ハックはありますか?
this 投稿と私の進行状況をマージする自分のソリューションを見つけました。
手順:
出力:
作業コード:
proguard-rules.pro:
-keepclassmembers class Android.support.design.internal.BottomNavigationMenuView {
boolean mShiftingMode;
}
BottomNavigationShiftHelper.Java:
public class BottomNavigationShiftHelper {
private final static String TAG = "DEBUG_BOTTOM_NAV_UTIL";
public static void disableShiftMode(BottomNavigationView view) {
BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
try {
Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
shiftingMode.setAccessible(true);
shiftingMode.setBoolean(menuView, false);
shiftingMode.setAccessible(false);
for (int i = 0; i < menuView.getChildCount(); i++) {
BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
item.setShiftingMode(false);
// set once again checked value, so view will be updated
item.setChecked(item.getItemData().isChecked());
}
} catch (NoSuchFieldException e) {
Log.d(TAG, "Unable to get shift mode field");
} catch (IllegalAccessException e) {
Log.d(TAG, "Unable to change value of shift mode");
}
}
}
Activity Sample.Java:
private void loadNavigationBar() {
BottomNavigationView bottomNavigationView = (BottomNavigationView)
findViewById(R.id.navigation_bar);
bottomNavigationView.getMenu().findItem(R.id.uncheckedItem).setChecked(true);
bottomNavigationView.findViewById(R.id.uncheckedItem).setVisibility(View.GONE);
BottomNavigationViewUtils.disableShiftMode(bottomNavigationView);
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.newList:
//Do The Math
break;
case R.id.loadList:
//Do The Math
break;
case R.id.settings:
//Do The Math
break;
}
return false;
}
});
}
BottomNavigationMenu.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto">
<item
Android:id="@+id/newList"
Android:enabled="true"
Android:icon="@drawable/new_list"
Android:title="@string/common.button.list.new"
app:showAsAction="withText" />
<item
Android:id="@+id/loadList"
Android:enabled="true"
Android:icon="@drawable/load"
Android:title="@string/common.button.list.load"
app:showAsAction="withText" />
<item
Android:id="@+id/settings"
Android:enabled="true"
Android:icon="@drawable/settings"
Android:title="@string/common.label.settings"
app:showAsAction="withText" />
<item
Android:id="@+id/uncheckedItem"
Android:title="" />
</menu>
BottomNavigationComponent(Activity.xml内):
<Android.support.design.widget.BottomNavigationView
Android:id="@+id/navigation_bar"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
app:itemIconTint="@color/white"
app:itemTextColor="@color/white"
Android:background="@drawable/BottomNavigationMenu.xml"
app:menu="@menu/supercart_bottom_navigation" />
mNavigationBottom.getMenu().setGroupCheckable(0, false, true);
すべてのアイテムの選択を解除するには、この拡張機能を作成します。
fun BottomNavigationView.uncheckAllItems() {
menu.setGroupCheckable(0, true, false)
for (i in 0 until menu.size()) {
menu.getItem(i).isChecked = false
}
menu.setGroupCheckable(0, true, true)
}
menu.setGroupCheckable(0、true、false)はそれを可能にします。 3番目のパラメーターはメニューを排他的ではなく、ループ内でチェック済みステータスを変更します。終了するには、メニューを再度排他に設定してください。
あなたのアイデアをありがとう。私は自分のlibにそれを実装しました。私はそれを反映することによってそれを行うより良い方法を持っています。したがって、スペースは表示されません。
興味があれば。ここをクリック: https://github.com/ittianyu/BottomNavigationViewEx
private void initBottomViewAndLoadFragments(final BottomNavigationViewEx bnve) {
bnve.enableAnimation(false);
bnve.enableShiftingMode(false);
bnve.enableItemShiftingMode(false);
// use the unchecked color for first item
bnve.setIconTintList(0, getResources().getColorStateList(R.color.bnv_unchecked_black));
bnve.setTextTintList(0, getResources().getColorStateList(R.color.bnv_unchecked_black));
bnve.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
private boolean firstClick = true;
private int lastItemId = -1;
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
// restore the color when click
if (firstClick) {
firstClick = false;
bnve.setIconTintList(0, getResources().getColorStateList(R.color.selector_bnv));
bnve.setTextTintList(0, getResources().getColorStateList(R.color.selector_bnv));
}
if (firstClick || lastItemId == -1 || lastItemId != item.getItemId()) {
lastItemId = item.getItemId();
} else {
return false;
}
// do stuff
return fillContent(item.getItemId());
}
});
}
-res/color/selector_bnv.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:color="@color/bnv_checked_white" Android:state_checked="true" />
<item Android:color="@color/bnv_unchecked_black" />
</selector>
-res/values/colors.xml
<color name="bnv_checked_white">@Android:color/white</color>
<color name="bnv_unchecked_black">@Android:color/black</color>
あなたの解決策はアイテム間のスペースを変えるようです
私の解決策があります:
「クリックされた色をクリックされていない色と同じに設定するだけです。」
例えば:
private void changeMenuItemCheckedStateColor(BottomNavigationView bottomNavigationView, String checkedColorHex, String uncheckedColorHex) {
int checkedColor = Color.parseColor(checkedColorHex);
int uncheckedColor = Color.parseColor(uncheckedColorHex);
int[][] states = new int[][] {
new int[] {-Android.R.attr.state_checked}, // unchecked
new int[] {Android.R.attr.state_checked}, // checked
};
int[] colors = new int[] {
uncheckedColor,
checkedColor
};
ColorStateList colorStateList = new ColorStateList(states, colors);
bottomNavigationView.setItemTextColor(colorStateList);
bottomNavigationView.setItemIconTintList(colorStateList);
}
すべてのアイテムのチェックを外したい場合は、
changeMenuItemCheckedStateColor(mBottomNavigationView, "#999999", "#999999");
色設定を復元したい場合は、
changeMenuItemCheckedStateColor(mBottomNavigationView, "FF743A", "999999");
これは、以下のマークが付いた2行のコードを変更したことを除いて、受け入れられた回答と同じです。 BottomNavigationItemViewsをループするとき、checkedを常にfalseに設定し、checkableもfalseに設定しました。これにより、メニュー項目のサイズが変更されなくなります。あなたはまだこのプロガードルールが必要です:
-keepclassmembers class Android.support.design.internal.BottomNavigationMenuView {
boolean mShiftingMode;
}
更新されたコード:
static void removeShiftMode(BottomNavigationView view)
{
BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
try
{
Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
shiftingMode.setAccessible(true);
shiftingMode.setBoolean(menuView, false);
shiftingMode.setAccessible(false);
for (int i = 0; i < menuView.getChildCount(); i++)
{
BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
item.setShiftingMode(false);
item.setChecked(false); // <--- This line changed
item.setCheckable(false); // <-- This line was added
}
}
catch (NoSuchFieldException e)
{
Log.e("ERROR NO SUCH FIELD", "Unable to get shift mode field");
}
catch (IllegalAccessException e)
{
Log.e("ERROR ILLEGAL ALG", "Unable to change value of shift mode");
}
}
承認された回答には例外があり、そのコードを実装できない最大アイテムを設定しているため、承認されたコードよりもシンプルなコードを取得し、最大アイテムでも機能します。
私はここから参照しました BottomNavigationViewサポートAndroidのカスタムTextSize
Dimen.xmlには次のように配置できます。
<dimen name="design_bottom_navigation_text_size" tools:override="true">10sp</dimen>
<dimen name="design_bottom_navigation_active_text_size" tools:override="true">10sp</dimen>
これを行うと、BottomNavigationViewの内部クラスが使用するdimenのデフォルト値を上書きします。だから気をつけて。
下部のナビゲーションビューが初期化されたonCreateメソッドでこのコードを設定します
mNavigationBottom.getMenu().setGroupCheckable(0, false, true);
最後に、下のナビゲーションバーを次のように設定します。
<com.google.Android.material.bottomnavigation.BottomNavigationView
Android:id="@+id/nav_view"
Android:layout_width="match_parent"
Android:layout_height="?attr/actionBarSize"
Android:layout_gravity="bottom"
Android:background="?android:attr/windowBackground"
Android:fitsSystemWindows="true"
app:labelVisibilityMode="labeled"
app:layout_anchorGravity="fill"
app:menu="@menu/bottom_nav_menu" />
このセットでは、app:labelVisibilityModeをlabeledに設定します
最良の答えmNavigationBottom.getMenu().setGroupCheckable(0, false, true)
はうまくいきませんでした。それでも、最初のアイテムが選択されていると表示されていました。
私にとってうまくいったのは、質問で行ったのとまったく同じように、非表示のアイテムを用意してそれを選択することです。
追加 app:labelVisibilityMode="labeled"
をBottomNavigationView
に追加すると、すべてのアイテムのタイトルが表示されたままになります。