如何使用adjustResize设置隐藏键盘下方的BottomNavigationView
Posted
技术标签:
【中文标题】如何使用adjustResize设置隐藏键盘下方的BottomNavigationView【英文标题】:How to hide the BottomNavigationView below keyboard with adjustResize set 【发布时间】:2017-06-22 11:03:03 【问题描述】:根据material design spec,当键盘出现时,BottomNavigationView
应该隐藏在它下面。但是,如果我在 Activity 的清单中设置 android:windowSoftInputMode="adjustResize"
,那么 BottomNavigationView
会移动到键盘上方。
我需要设置adjustResize
以在键盘打开时启用滚动到屏幕底部。但是,我不希望 BottomNavigationView
可见。这个可以吗?
目前的样子:
布局 XML(实际上会有一个 FrameLayout
,EditText
位于其中,EditText
位于其中):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_
android:layout_>
<EditText
android:layout_
android:layout_
android:hint="Input"
android:layout_gravity="center"
android:layout_centerVertical="true"/>
<android.support.design.widget.BottomNavigationView
android:layout_
android:layout_
android:layout_alignParentBottom="true"
app:itemBackground="@color/colorPrimary"
app:menu="@menu/menu_bottom_navigation"
app:itemIconTint="@android:color/white"
app:itemTextColor="@android:color/white"/>
</RelativeLayout>
【问题讨论】:
你解决了吗? 不,我没有,但是一个建议是当用户点击一个字段(包括底部导航栏)然后当用户点击键盘上方的屏幕或滚动键盘时,将所有内容隐藏在键盘后面就消失了。这不是很好,但我认为它比浮动导航栏更好的用户体验。 Spotify 应用会执行此操作。 我也遇到了同样的问题...如果您找到解决方案,请告诉我... 大家好!我已经发布了一个新的答案,它实际上解决了这个问题。写这个评论,因为我很晚才能回答,而最高票数的答案并不能真正解决这个问题,这可能是 OP 尚未接受它的原因。所以请看一遍我的答案。 【参考方案1】:将此添加到清单中的活动
android:windowSoftInputMode="adjustPan"
很喜欢
<activity android:name=".feature.home.HomeActivity"
android:windowSoftInputMode="adjustPan"/>
【讨论】:
当键盘打开但不允许滚动视图工作时,保持底部导航视图粘在底部是一件好事。 这不是底部导航的解决方案。 问题中明确提到如何使用adjustResize而不是adjustPan。【参考方案2】:解决方案(或其他方法)
我经历了与 OP 所说的完全相同的情况,我在屏幕底部显然有一个 BottomNavigationView
,而在上面有一个 ScrollView
。
现在,如果我们在活动中执行
adjustPan
,那么当键盘出现但滚动不起作用时,BottomNavigationView
将保持在底部。如果我们执行
adjustResize
,则滚动有效,但 BottomNavigationView 被推到键盘顶部。
我认为以下可以是相同的两种方法。
方法 1
只需在键盘显示/隐藏上将可见性设置为消失/可见。这是相同的快速解决方法。您可以在下一个方法中自行获取键盘隐藏/显示事件的侦听器。
为了让它看起来更有趣,您可以尝试使用某种动画来显示/隐藏 BottomNavigationView。
方法 2
更好的方法(材料设计方法)是使用CoordinatorLayout
和滚动行为(与您可能看到的CollapsingToolBar
相同)。
下面是布局文件
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_
android:layout_>
<android.support.design.widget.AppBarLayout
android:layout_
android:layout_>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_
android:layout_
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:title="@string/title"
app:titleTextColor="@android:color/white" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="@+id/nestedScrollView"
android:layout_
android:layout_
app:layout_behavior="@string/appbar_scrolling_view_behavior">
------ Your Contents --------
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.BottomNavigationView
android:id="@+id/navigation"
android:layout_
android:layout_
android:layout_gravity="bottom"
android:background="?android:attr/windowBackground"
app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior"
app:menu="@menu/navigation" />
</android.support.design.widget.CoordinatorLayout>
就是这样,现在您可以看到 BottomNavigationView 在滚动到底部和顶部等时隐藏/显示。但是在一种情况下,您可能会遇到另一个问题,即当键盘被隐藏时,如果内容太小而无法滚动,
问题是,当键盘打开并且您滚动到隐藏 BottomNavigationView 的底部时,现在如果您按下后退按钮,键盘会隐藏,但 BottomNavigationView 仍然保持隐藏状态。现在,由于内容不可滚动,因此如果您尝试滚动,它不会显示 BottomNavigationView。要再次显示它,您需要做的是,再次使键盘可见,然后向上滚动,当显示 BottomNavigationView 时,然后按返回按钮。
我试图用这种方法解决这个问题,
添加全局侦听器以查看键盘是显示还是隐藏。我在这里使用的代码是,(它在 Kotlin 中,但是如果需要,您可以轻松地将其转换为 Java 版本)
private fun addKeyboardDetectListener()
val topView = window.decorView.findViewById<View>(android.R.id.content)
topView.viewTreeObserver.addOnGlobalLayoutListener
val heightDifference = topView.rootView.height - topView.height
if(heightDifference > dpToPx(this, 200F))
// keyboard shown
Log.d(TAG, "keyboard shown")
else
// keyboard hidden
Log.d(TAG, "keyboard hidden")
val behavior = (navigation.layoutParams as CoordinatorLayout.LayoutParams).behavior as HideBottomViewOnScrollBehavior
behavior.slideUp(navigation)
fun dpToPx(context: Context, valueInDp: Float) : Float
val displayMetrics = context.resources.displayMetrics
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, displayMetrics)
最后一件事,如果您使用支持库版本 28.0.0,那么您将看到 behavior.slideUp(navigation)
方法受到保护,因此您不能从您的活动等中调用它。
不过,Google 的 Android 团队已经在新的material-components
中公开了这些方法。 Check this 所以只需在您的项目中导入材料组件并改用此类。
除此之外,您还可以尝试更多实验,例如在键盘隐藏/显示上以编程方式调用 slideUp 或 slideDown 等。
附:我花了很多时间来了解这种完全有效的方法,所以想在这里分享它,这样可以节省别人的时间。
【讨论】:
这是一个很好的方法,但对我来说当编辑文本时,除非用户滚动,否则仍会显示焦点键盘 @Nux 当 EditText 获得焦点时,应显示键盘。你的意思是说当 EditText 失去焦点时,键盘仍然显示? 感谢您的回复,这只是一个小错误,已经解决了【参考方案3】:还有另一种解决方案,它不需要adjustSpan
,但它仅适用于API >= 21
。您可以通过跟踪系统插图来检测键盘是否显示/隐藏。假设你有BottomNavigationView
,它是LinearLayout
的子元素,你需要在显示键盘时隐藏它:
> LinearLayout
> ContentView
> BottomNavigationView
您需要做的就是以这种方式扩展LinearLayout
:
public class KeyboardAwareLinearLayout extends LinearLayout
public KeyboardAwareLinearLayout(Context context)
super(context);
public KeyboardAwareLinearLayout(Context context, @Nullable AttributeSet attrs)
super(context, attrs);
public KeyboardAwareLinearLayout(Context context,
@Nullable AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
public KeyboardAwareLinearLayout(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes)
super(context, attrs, defStyleAttr, defStyleRes);
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets)
int childCount = getChildCount();
for (int index = 0; index < childCount; index++)
View view = getChildAt(index);
if (view instanceof BottomNavigationView)
int bottom = insets.getSystemWindowInsetBottom();
if (bottom >= ViewUtils.dpToPx(200))
view.setVisibility(GONE);
else
view.setVisibility(VISIBLE);
return insets;
这个想法是,当显示键盘时,系统插入会更改为相当大的.bottom
值。
【讨论】:
【参考方案4】:有时从其他布局复制粘贴会发生这种情况。在我的情况下,我只是从布局文件中删除tools:context="Your class name"
。谢谢
【讨论】:
【参考方案5】:作为android:windowSoftInputMode="adjustResize"
的一种替代方法,你可以试试这个。
从您的OnCreate
调用此方法- 键盘启动后,您可以更改不需要显示的视图的可见性!
当键盘按下时再次显示它们。
public void checkKeyBoardUp()
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
@Override
public void onGlobalLayout()
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
int heightDiff = rootView.getRootView().getHeight() - (r.bottom - r.top);
if (heightDiff > 100) // if more than 100 pixels, its probably a keyboard...
//ok now we know the keyboard is up...
whatEverView.setVisibility(View.INVISIBLE);
else
//ok now we know the keyboard is down...
whatEverView.setVisibility(View.VISIBLE);
);
【讨论】:
它是正确的解决方案,但要正确检查键盘状态,请使用link 这不起作用:空白留在导航栏的位置 最好使用View.GONE
而不是View.INVISIBLE
以上是关于如何使用adjustResize设置隐藏键盘下方的BottomNavigationView的主要内容,如果未能解决你的问题,请参考以下文章