从BottomNavigationView中移除动画/移位模式 (Android)

33

我正在开发一个应用程序,在其中有一个BottomNavigationView。一切都很正常,直到我进入Activity。

导航如下:

enter image description here

问题是它具有默认的动画效果,因此每次活动元素比其他元素更高。

另一个例子:

enter image description here

所以我的问题是如何摆脱这个默认的动画效果,并且在切换它们时使每个项目都对齐?

我的代码:

public class MainActivity extends AppCompatActivity {
    private BottomNavigationView bottomNavigationView;
    private Fragment fragment;
    private FragmentManager fragmentManager;
    private FragmentTransaction transaction;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setupBottomBar();
    }

    private void setupBottomBar() {
        bottomNavigationView = (BottomNavigationView)findViewById(R.id.bottomBar);
        fragmentManager = getSupportFragmentManager();
        fragment = new CardDeckFragment();
        transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.activity_main, fragment).commit();
        bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                switch (item.getItemId()){
                    case R.id.action_card_deck:{
                        Toast.makeText(MainActivity.this, "Card Deck Selected", Toast.LENGTH_SHORT).show();
                        fragment = new CardDeckFragment();
                        break;
                    }
                    case R.id.action_favorites:{
                        Toast.makeText(MainActivity.this, "Favorites Selected", Toast.LENGTH_SHORT).show();
                        fragment = new FavoritesFragment();
                        break;
                    }
                    case R.id.action_favorites_another:{
                        Toast.makeText(MainActivity.this, "Image Selected", Toast.LENGTH_SHORT).show();
                        fragment = new ImageFragment();
                        break;
                    }
                    case R.id.action_profile:{
                        Toast.makeText(MainActivity.this, "Profile Selected", Toast.LENGTH_SHORT).show();
                        fragment = new ProfileFragment();
                        break;
                    }
                    case R.id.action_menu:{
                        Toast.makeText(MainActivity.this, "Menu Selected", Toast.LENGTH_SHORT).show();
                        fragment = new MenuFragment();
                        break;
                    }
                }

                transaction = fragmentManager.beginTransaction();
                transaction.replace(R.id.activity_main, fragment).commit();
                return true;
            }
        });



    }
}

以及我的布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.realtimegaming.androidnative.testproject.MainActivity">

    <android.support.design.widget.BottomNavigationView
        android:id="@+id/bottomBar"
        android:layout_alignParentBottom="true"
        android:background="@color/brown"
        android:layout_gravity="bottom"
        android:gravity="bottom"
        android:layout_marginTop="?attr/actionBarSize"
        app:itemBackground="@color/colorPrimary"
        app:menu="@menu/bottom_navigation_main"
        app:itemIconTint="@color/white"
        android:fitsSystemWindows="true"
        android:animateLayoutChanges="false"
        android:splitMotionEvents="false"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</RelativeLayout>

你尝试过移除 animateLayoutChangessplitMotionEvents 属性吗? - Jay Rathod
你能举个例子吗? - user7157256
希望谷歌很快会发布这个版本的BottomNavigationView,其中包括在xml和java中设置setShiftingMode方法的功能。 - MidasLefko
https://dev59.com/Y1gR5IYBdhLWcg3wJ6tw#47544809 - azamatikus
如果您想要完全删除动画:https://dev59.com/rFkS5IYBdhLWcg3wP0Rq#51052247 - Fred Porciúncula
显示剩余2条评论
1个回答

75

好的,我发现了一种方法,希望能对其他人有所帮助。默认情况下,当 BottomNavigationView 中的项目数超过 3 个时,它会添加 shiftingmode = true。

目前你无法通过现有的 API 更改它,唯一的禁用 shift mode 的方法是使用反射。

因此,我们可以使用这个帮助程序来摆脱这个问题:

class BottomNavigationViewHelper {

    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);
                // set once again checked value, so view will be updated
                item.setChecked(item.getItemData().isChecked());
            }
        } 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 bottomNavigationView = (BottomNavigationView)findViewById(R.id.bottomBar);
BottomNavigationViewHelper.removeShiftMode(bottomNavigationView);

希望这篇帮助有同样问题的人!!!

请记住,在您更改BottomNavigationView中的菜单项时,需要每次执行此方法。

更新

根据不同的stackoverflow问题,您还需要更新proguard配置文件(例如proguard-rules.pro),上面的代码使用反射,并且如果proguard混淆mShiftingMode字段,则无法正常工作。

-keepclassmembers class android.support.design.internal.BottomNavigationMenuView { 
    boolean mShiftingMode; 
}

94
天啊,安卓开发真是太疯狂了…… - Chris Jeon
2
这不适用于最新的设计支持库。 - Rajesh.k
3
在支持库28.0.0-alpha3中,“setShiftingMode”被重命名为“setShifting”。 - Eric B.
3
为什么不能在XML中保留一个属性来实现这个? - Pankaj
2
很遗憾,它无法与com.google.android.material.bottomnavigation.BottomNavigationView;导入一起使用。 - Yvgen
显示剩余13条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接