Open chriscoomber opened 6 years ago
Internet searches seem to say something like either:
Use adjustPan
, but this is generally not the right solution if you are using ScollView
s or action bars.
Listen for the keyboard opening and closing, and show/hide the botton nav bar
EditText
, though this is not reliable as long-pressing on an EditText
(e.g. to paste text) does not always show the keyboard, despite focusing the EditText
.mBottomNav.hideBottomNavigation(false);
.However, these don't work for me because:
They still don't really look like the Materials Guidelines. The hiding the bottom nav bar just doesn't look like the keyboard covering up the bottom nav bar.
I can't use adjustPan
Because my bottom navigation is always showing, then the content view must all appear above the bottom navigation view - there must not be any content underneath the bottom navigation view. This means that the navigation view must "push up" the content view, e.g. by putting them both in a LinearLayout
. (Note that in the demo in this repository, the bottom navigation view overlays the content.) When I hide the bottom navigation view with mBottomNav.hideBottomNavigation(false);
, it doesn't change the layout bounds of the view, so there is still a blank rectangle below the content view, above the keyboard. If I instead hide it with mBottomNav.setVisibility(View.GONE)
, then the UI looks glitchy at the moment when it adjusts layout bounds:
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:
<?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>
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;
}
}
}
In the Material Design guidelines, it says:
(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:
ScrollView
s, so I think I need to useadjustResize
in the activity's manifest entry (adjustPan
would not interact well with the scrolling).To try to avoid the X-Y problem, I'll stop here, and post what I've tried so far as a comment.