aurelhubert / ahbottomnavigation

A library to reproduce the behavior of the Bottom Navigation guidelines from Material Design.
3.83k stars 682 forks source link

Can't get keyboard to appear over bottom navigation #343

Open chriscoomber opened 6 years ago

chriscoomber commented 6 years ago

In the Material Design guidelines, it says:

Bottom sheets and keyboards appear in front of the bottom nav bar, temporarily covering it.

(There's quite a nice video in the "elevation" section, where a "bottom sheet" covers the bottom navigation.)

How should this work in general? It doesn't seem supported by default - when I add an EditText to one a fragment, the bottom navigation bar does not hide when the keyboard appears.

Additional complications in my case.

In my specific case, I have the following other requirements:

  1. The content view can contain stuff like ScrollViews, so I think I need to use adjustResize in the activity's manifest entry (adjustPan would not interact well with the scrolling).
  2. The bottom navigation should not disappear when scrolling (it should always be showing).

To try to avoid the X-Y problem, I'll stop here, and post what I've tried so far as a comment.

chriscoomber commented 6 years ago

Things I've tried

Internet searches seem to say something like either:

  1. Use adjustPan, but this is generally not the right solution if you are using ScollViews or action bars.

  2. Listen for the keyboard opening and closing, and show/hide the botton nav bar

However, these don't work for me because:

The only passable solution I have so far is to animate the bottom navigation view shrinking, including shrinking its layout bounds. However this just looks way more crap than the example in the Materials Guidelines. Here's some sample code:

activity.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:application="http://schemas.android.com/apk/res-auto">

    <!-- Avoid content appearing underneath the BottomNavigationView by adding a margin.
            We do this instead of using a LinearLayout (or something like that) so that we can adjust this
            margin in an animation, and slide the BottomNavigationView off screen. If we instead tried to
            adjust the height of the BottomNavigationView, it would get squashed and would render wrong. -->
    <!-- In the real world this view would be some Coordinator Layout with a ViewPager, or something -->
    <View
        android:id="@+id/the_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="@dimen/bottom_navigation_height"/>

    <com.aurelhubert.ahbottomnavigation.AHBottomNavigation
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="@dimen/bottom_navigation_height"
        android:layout_gravity="bottom"
        android:background="@color/white"/>

</FrameLayout>

MyActivity.java (omitting any of the code of the actual content view)

import android.animation.ValueAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Px;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;

import com.example.R;

import net.yslibrary.android.keyboardvisibilityevent.KeyboardVisibilityEvent;

public class MyActivity extends Activity
{
    private boolean mBottomNavigationIsHidden;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        KeyboardVisibilityEvent.setEventListener(
            this,
            this::showOrHideBottomNavigation);
    }

    /**
     * Show or hide the bottom navigation menu depending on whether the keyboard is open or closed.
     * @param keyboardIsVisible whether the keyboard is open or closed.
     */
    private void showOrHideBottomNavigation(boolean keyboardIsVisible)
    {
        View contentView = findViewById(R.id.the_content);
        View bottomNavigationView = findViewById(R.id.bottom_navigation);
        @Px int bottomNavigationHeight = (int) getResources()
            .getDimension(R.dimen.bottom_navigation_height);

        if (keyboardIsVisible && !mBottomNavigationIsHidden)
        {
            ValueAnimator animator = ValueAnimator.ofInt(0, bottomNavigationHeight);
            animator.setInterpolator(new DecelerateInterpolator());
            animator.addUpdateListener((animation) ->
            {
                Integer value = (Integer) animation.getAnimatedValue();

                // Shift the navigation bar off the screen
                bottomNavigationView.setTranslationY(value);

                // Shrink the margin at the same rate
                ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) contentView.getLayoutParams();
                params.setMargins(0, 0, 0, bottomNavigationHeight - value);
                contentView.setLayoutParams(params);
            });
            animator.setDuration(150);
            animator.start();

            mBottomNavigationIsHidden = true;
        }
        else if (!keyboardIsVisible && mBottomNavigationIsHidden)
        {
            ValueAnimator animator = ValueAnimator.ofInt(0, bottomNavigationHeight);
            animator.setInterpolator(new AccelerateInterpolator());
            animator.addUpdateListener((animation) ->
            {
                Integer value = (Integer) animation.getAnimatedValue();

                // Shift the navigation bar back onto the screen
                bottomNavigationView.setTranslationY(bottomNavigationHeight - value);

                // Expand the margin at the same rate
                ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) contentView.getLayoutParams();
                params.setMargins(0, 0, 0, value);
                contentView.setLayoutParams(params);
            });
            animator.setDuration(300);
            animator.start();

            mBottomNavigationIsHidden = false;
        }
    }
}