BottomNavigationView занимает место после клика - PullRequest
0 голосов
/ 30 мая 2018

Я использую BottomNavigationView в своем коде, чтобы показать 5 значков.Когда я нажимаю на иконку, открывается новый фрагмент.

У меня есть 2 проблемы с реализацией BottomNavigationView

  1. Кнопки белого цвета, но они выглядят серыми в BottomNavigationView,Как я могу заставить его выглядеть белым?Я также установил iconTint в файл белым, но все равно он выглядит серым / черным.
  2. Когда я нажимаю на иконку, иконка выделяется и появляется спереди, а при выключенном виде другие пиктограммы сзади.Как я могу переопределить это поведение, все значки должны занимать одинаковое пространство даже при нажатии.

Изменить: 2-й вопрос будет решен этим вопросом .

Код BottomNavigationView в макетефайл:

<android.support.design.widget.BottomNavigationView
    android:id="@+id/main_screen_botton_nav"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    android:background="@color/colorPrimaryDark"
    app:itemTextColor="@color/cardview_light_background"
    app:layout_behavior=".Common.BottomNavigationBehavior"
    app:menu="@menu/mainscreen_bottomnav" />

Файл меню:

 <menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/main_screen_home"
        android:icon="@drawable/home"
        android:iconTint="@color/cardview_light_background"
        android:title="Home"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/main_screen_xx"
        android:icon="@drawable/xx"
        android:iconTint="@color/cardview_light_background"
        android:title="xx"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/main_screen_weather"
        android:icon="@drawable/cloudy"
        android:iconTint="@color/cardview_light_background"
        android:title="Weather"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/main_screen_banking"
        android:icon="@drawable/yy"
        android:iconTint="@color/cardview_light_background"
        android:title="Finance"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/main_screen_settings"
        android:icon="@drawable/settings"
        android:iconTint="@color/cardview_light_background"
        android:title="Settings"
        app:showAsAction="ifRoom" />
 </menu>

В основной деятельности:

    BottomNavigationView bottomNavigationView = findViewById(R.id.main_screen_botton_nav);
    bottomNavigationView.setOnNavigationItemSelectedListener(this);

.

enter image description here

1 Ответ

0 голосов
/ 04 июня 2018

Вы должны попробовать это.он отлично работает в моем приложении.

import android.support.design.internal.BottomNavigationItemView;
import android.support.design.internal.BottomNavigationMenuView; 
import android.support.design.widget.BottomNavigationView; 
import android.util.Log;
import java.lang.reflect.Field;

public class BottomNavigationViewHelper { 
    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);
                item.setChecked(item.getItemData().isChecked());
            } 
        } catch (NoSuchFieldException e) {
            Log.e("BNVHelper", e.getMessage());
        } catch (IllegalAccessException e) {
            Log.e("BNVHelper", e.getMessage());
        } 
    } 
} 

Вы можете использовать этот класс как:

BottomNavigationView bottomNavigation = (BottomNavigationView) findViewById(R.id.bottom_navigation);
BottomNavigationViewHelper.disableShiftMode(bottomNavigation);

BottomNavigationView:

    <android.support.design.widget.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:layout_alignParentBottom="true"
        android:layout_gravity="bottom|end"
        app:itemBackground="@color/bottom_bar_unselect"
        app:layout_behavior="com.cmexpertise.beautyapp.view.BottomNavigationBehavior"
        app:itemIconTint="@drawable/navigation_background_text"
        app:itemTextColor="@drawable/navigation_background_text"
        app:menu="@menu/my_navigation_items" />

BottomNavigationBehavior.Java:

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorCompat;
import android.support.v4.view.animation.LinearOutSlowInInterpolator;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;



/**

 */
public final class BottomNavigationBehavior<V extends View> extends VerticalScrollingBehavior<V> {
    private static final Interpolator INTERPOLATOR = new LinearOutSlowInInterpolator();
    private final BottomNavigationWithSnackbar mWithSnackBarImpl = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? new LollipopBottomNavWithSnackBarImpl() : new PreLollipopBottomNavWithSnackBarImpl();
    private int mTabLayoutId;
    private boolean hidden = false;
    private ViewPropertyAnimatorCompat mOffsetValueAnimator;
    private ViewGroup mTabLayout;
    private int mSnackbarHeight = -1;
    private boolean scrollingEnabled = true;
    private boolean hideAlongSnackbar = false;
    int[] attrsArray = new int[]{
            android.R.attr.id, android.R.attr.elevation};
    private int mElevation = 8;

    public BottomNavigationBehavior() {
        super();
    }

    public BottomNavigationBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs,
                attrsArray);
        mTabLayoutId = a.getResourceId(0, View.NO_ID);
        mElevation = a.getResourceId(1, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mElevation, context.getResources().getDisplayMetrics()));
        a.recycle();
    }

    public static <V extends View> BottomNavigationBehavior<V> from(@NonNull V view) {
        ViewGroup.LayoutParams params = view.getLayoutParams();
        if (!(params instanceof CoordinatorLayout.LayoutParams)) {
            throw new IllegalArgumentException("The view is not a child of CoordinatorLayout");
        }
        CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) params)
                .getBehavior();
        if (!(behavior instanceof BottomNavigationBehavior)) {
            throw new IllegalArgumentException(
                    "The view is not associated with BottomNavigationBehavior");
        }
        return (BottomNavigationBehavior<V>) behavior;
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) {
        mWithSnackBarImpl.updateSnackbar(parent, dependency, child);
        return dependency instanceof Snackbar.SnackbarLayout;
    }

    @Override
    public void onDependentViewRemoved(CoordinatorLayout parent, V child, View dependency) {
        updateScrollingForSnackbar(dependency, child, true);
        super.onDependentViewRemoved(parent, child, dependency);
    }

    private void updateScrollingForSnackbar(View dependency, V child, boolean enabled) {
        if (dependency instanceof Snackbar.SnackbarLayout) {
            scrollingEnabled = enabled;
            if (!hideAlongSnackbar && ViewCompat.getTranslationY(child) != 0) {
                ViewCompat.setTranslationY(child, 0);
                hidden = false;
                hideAlongSnackbar = true;
            } else if (hideAlongSnackbar) {
                hidden = true;
                animateOffset(child, -child.getHeight());
            }
        }
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, V child, View dependency) {
        updateScrollingForSnackbar(dependency, child, false);
        return super.onDependentViewChanged(parent, child, dependency);
    }

    @Override
    public boolean onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection) {
        boolean layoutChild = super.onLayoutChild(parent, child, layoutDirection);
        if (mTabLayout == null && mTabLayoutId != View.NO_ID) {
            mTabLayout = findTabLayout(child);
            elevateNavigationView();
        }

        return layoutChild;
    }

    @Nullable
    private ViewGroup findTabLayout(@NonNull View child) {
        if (mTabLayoutId == 0) return null;
        return (ViewGroup) child.findViewById(mTabLayoutId);
    }

    @Override
    public void onNestedVerticalOverScroll(CoordinatorLayout coordinatorLayout, V child, @ScrollDirection int direction, int currentOverScroll, int totalOverScroll) {
    }

    @Override
    public void onDirectionNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed, @ScrollDirection int scrollDirection) {
        handleDirection(child, scrollDirection);
    }

    private void handleDirection(V child, @ScrollDirection int scrollDirection) {
        if (!scrollingEnabled) return;
        if (scrollDirection == ScrollDirection.SCROLL_DIRECTION_DOWN && hidden) {
            hidden = false;
            animateOffset(child, 0);
        } else if (scrollDirection == ScrollDirection.SCROLL_DIRECTION_UP && !hidden) {
            hidden = true;
            animateOffset(child, child.getHeight());
        }
    }

    @Override
    protected boolean onNestedDirectionFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY, @ScrollDirection int scrollDirection) {
        handleDirection(child, scrollDirection);
        return true;
    }

    private void animateOffset(final V child, final int offset) {
        ensureOrCancelAnimator(child);
        mOffsetValueAnimator.translationY(offset).start();
    }



    private void ensureOrCancelAnimator(@NonNull  V child) {
        if (mOffsetValueAnimator == null) {
            mOffsetValueAnimator = ViewCompat.animate(child);
            mOffsetValueAnimator.setDuration(100);
            mOffsetValueAnimator.setInterpolator(INTERPOLATOR);
        } else {
            mOffsetValueAnimator.cancel();
        }
    }

    private void elevateNavigationView() {
        if (mTabLayout != null) {
            ViewCompat.setElevation(mTabLayout, mElevation);
        }
    }

    public boolean isScrollingEnabled() {
        return scrollingEnabled;
    }

    public void setScrollingEnabled(boolean scrollingEnabled) {
        this.scrollingEnabled = scrollingEnabled;
    }

    public void setHidden(V view, boolean bottomLayoutHidden) {
        if (!bottomLayoutHidden && hidden) {
            animateOffset(view, 0);
        } else if (bottomLayoutHidden && !hidden) {
            animateOffset(view, -view.getHeight());
        }
        hidden = bottomLayoutHidden;
    }

    private interface BottomNavigationWithSnackbar {
        void updateSnackbar(CoordinatorLayout parent, View dependency, View child);
    }

    private class PreLollipopBottomNavWithSnackBarImpl implements BottomNavigationWithSnackbar {

        @Override
        public void updateSnackbar(CoordinatorLayout parent, View dependency, View child) {
            if (dependency instanceof Snackbar.SnackbarLayout) {
                if (mSnackbarHeight == -1) {
                    mSnackbarHeight = dependency.getHeight();
                }

                int targetPadding = child.getMeasuredHeight();

                int shadow = (int) ViewCompat.getElevation(child);
                ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) dependency.getLayoutParams();
                layoutParams.bottomMargin = targetPadding - shadow;
                child.bringToFront();
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
                    child.getParent().requestLayout();
                    ((View) child.getParent()).invalidate();
                }

            }
        }
    }

    private class LollipopBottomNavWithSnackBarImpl implements BottomNavigationWithSnackbar {

        @Override
        public void updateSnackbar(CoordinatorLayout parent, View dependency, View child) {
            if (dependency instanceof Snackbar.SnackbarLayout) {
                if (mSnackbarHeight == -1) {
                    mSnackbarHeight = dependency.getHeight();
                }
                int targetPadding = (mSnackbarHeight +
                        child.getMeasuredHeight());
                dependency.setPadding(dependency.getPaddingLeft(),
                        dependency.getPaddingTop(), dependency.getPaddingRight(), targetPadding
                );
            }
        }
    }
}

navigation_background_text.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/colorPrimary" android:state_checked="true" />
    <item android:color="@color/white" />
</selector>
...