Подтвердить что ты не робот

BottomNavigationView - эффект тени и пульсации

Я был очень рад, когда BottomNavigationView был выпущен неделю назад, но мне приходится сталкиваться с некоторыми проблемами, из-за которых я не могу его решить, например чтобы увидеть тень над BottomNavigationView, так же, как Google Android Android App показывает нам:

Тень над нижней панелью навигации

Если мы нажмем на пункт меню Google Фото, мы увидим эффект пульсации, который окрашен в синий цвет, как цвет значка и текста (если выбран).

Реализация решения, предоставляемого только Google, показывает серый цвет эффекта пульсации, и, что еще хуже, он не отображается, когда мы меняем цвет фона в представлении bottomnavigationview (design:itemBackground="...").

Кто-то знает, как его решить?

4b9b3361

Ответ 1

Вот чего я достиг:

Волновой эффект + высота над уровнем моря

Я создал демо на GitHub, чтобы помочь вам.

Прежде всего используйте последнюю compile "com.android.support:design:$SUPPORT_VERSION" библиотеки поддержки compile "com.android.support:design:$SUPPORT_VERSION"

Работает только если вы установите белый цвет фона android:background="@android:color/white"

Обратите внимание, что волновой эффект исчезнет, если вы используете свойство app:itemBackground или в вашем случае его design:itemBackground="...", поэтому просто удалите его.

<android.support.design.widget.BottomNavigationView
    android:id="@+id/bottom_navigation"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:background="@android:color/white"
    app:elevation="16dp"
    app:itemIconTint="@drawable/nav_item_color_state"
    app:itemTextColor="@drawable/nav_item_color_state"
    app:menu="@menu/bottom_navigation_main" />

Обработка включена/отключена:

Вам необходимо создать селекторный файл:

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

Если вы хотите изменить стандартный эффект серой ряби, измените colorControlHighlight colorControlHighlight в AppTheme, чтобы оно выглядело следующим образом:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="colorControlHighlight">@color/colorPrimaryRipple</item>
</style>

Используйте 26% альфа для цветной ряби.

<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryRipple">#423F51B5</color>

Ответ 2

  • Для использования темной тени в вашем BottomNavigationView app:elevation="8dp".
  • И для эффекта Ripples вам просто нужно удалить app:itemBackground и установить android:background на белый цвет, подобный android:background="@android:color/white"

Полный пример ниже:

<android.support.design.widget.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:layout_alignParentBottom="true"
        android:background="@android:color/white"
        android:clickable="true"
        app:elevation="8dp"
        app:itemIconTint="@drawable/nav_item_color_state"
        app:itemTextColor="@drawable/nav_item_color_state"
        app:menu="@menu/my_navigation_items" />

Ответ 3

Возьмем этот FrameLayout который рисует тень, и этот градиент для рисования xml:

public class DrawShadowFrameLayout extends FrameLayout {
    private Drawable mShadowDrawable;
    private final int mShadowElevation = 8;
    private int mWidth;
    private int mHeight;
    private boolean mShadowVisible = true;

    public DrawShadowFrameLayout(Context context) {
        this(context, null, 0);
    }

    public DrawShadowFrameLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DrawShadowFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mShadowDrawable = ContextCompat.getDrawable(getContext(), R.drawable.shadow);
        if (mShadowDrawable != null) {
            mShadowDrawable.setCallback(this);
        }
        setWillNotDraw(!mShadowVisible);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;
        updateShadowBounds();
    }


    private void updateShadowBounds() {
        if (mShadowDrawable != null) {
            mShadowDrawable.setBounds(0, 0, mWidth, mShadowElevation);
        }
        ViewCompat.postInvalidateOnAnimation(this);
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        if (mShadowDrawable != null && mShadowVisible) {
            getBackground().setBounds(0, mShadowDrawable.getBounds().bottom, mWidth, mHeight);
            mShadowDrawable.draw(canvas);
        }
    }

    public void setShadowVisible(boolean shadowVisible) {
        setWillNotDraw(!mShadowVisible);
        updateShadowBounds();
    }

    int getShadowElevation() {
        return mShadowVisible ? mShadowElevation : 0;
    }

}

Оберните ваш BottomNavigationView внутри этого макета следующим образом:

<DrawShadowFrameLayout>
  <BottomNavigationView />
</DrawShadowFrameLayout>

К сожалению, естественная тень нарисована под видом, мы должны подражать этой восходящей тени сами.

Не забудьте добавить android:elevation="8dp" для DrawShadowFrameLayout.

Другой подход заключается в расширении BottomNavigationView и переопределении draw() чтобы сделать то же самое. Это поможет вам потерять один FrameLayout в вашей иерархии представлений.

enter image description here Zoomed

Ответ 4

Это проблема в библиотеке Design и сообщается здесь.

Теневая часть этого вопроса уже разрешена, поэтому вы должны обновить свои зависимости Gradle до 25.0.1 для библиотеки поддержки и дизайна.

Инженеры Google настаивают на том, что проблема эффекта пульсации также исправлена, но я не смог заставить ее работать правильно.

Пример использования XML для BottomNavigationView можно увидеть здесь:

<android.support.design.widget.BottomNavigationView
    android:id="@+id/bottom_navigation"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:background="@android:color/black"
    app:itemBackground="@android:color/white"
    app:itemIconTint="@drawable/bottom_navigation_selector"
    app:itemTextColor="@drawable/bottom_navigation_selector"
    app:menu="@menu/bottom_navigation_menu" />

Назовите проблему, чтобы добавить к ней информацию.

Ответ 5

Вы можете добавить селектор к своей кнопке, например:

android:background="@drawable/my_selector"

/res/drawable/my_selector.xml:

<ripple android:color="@color/my_favourite_color"
    xmlns:android="http://schemas.android.com/apk/res/android" />

Подробнее: RippleDrawable

Ответ 6

Я нашел решение проблемы волнового эффекта.

1) Поскольку android: background и app: itemBackground не работают правильно, удалите их обоих из BottomNavigationView.

2) Создайте новый FrameLayout и поместите BottomNavigationView в FrameLayout.

3) изменить эти свойства FrameLayout:

android:layout_width="match_parent"
android:layout_height="wrap_content"

4) Наконец, добавьте нужный цвет для ButtomNavigationView в FrameLayout как android: background.

Пример:

<FrameLayout
 android:id="@+id/buttomnavigation_container"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:background="@color/blue"><!--Background color for BNV-->
 <android.support.design.widget.BottomNavigationView
    android:id="@+id/nav_view"
    android:layout_width="match_parent"
    android:layout_height="56dp"
    app:itemIconTint="@color/bottom_navigation_colors"
    app:itemTextColor="@color/bottom_navigation_colors"
    app:labelVisibilityMode="labeled"
    app:menu="@menu/bottom_nav_menu"/>
</FrameLayout>

bottom_navigation_colors.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
   <item
        android:state_checked="true"
        android:color="#FFFFFF" />
   <item
       android:state_checked="false"
       android:color="#C7FFFFFF" />
</selector>

Image