web-dev-qa-db-ja.com

adjustResizeセットでキーボードの下にあるBottomNavigationViewを非表示にする方法

材料設計仕様 によると、キーボードが表示されると、BottomNavigationViewはその下に隠れます。ただし、Android:windowSoftInputMode="adjustResize"アクティビティのマニフェストでBottomNavigationViewがキーボードの上に移動します。

キーボードが開いているときに画面の下部へのスクロールを有効にするには、adjustResizeを設定する必要があります。ただし、BottomNavigationViewを表示したくありません。これはできますか?

現在の外観:

enter image description here

レイアウト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_width="match_parent"
    Android:layout_height="match_parent">

    <EditText
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:hint="Input"
        Android:layout_gravity="center"
        Android:layout_centerVertical="true"/>

    <Android.support.design.widget.BottomNavigationView
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        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>
29
willjgriff

これをマニフェストのアクティビティに追加します

Android:windowSoftInputMode="adjustPan"

以下のようなので

<activity Android:name=".feature.home.HomeActivity" 
 Android:windowSoftInputMode="adjustPan"/>
45
sabbibJAVA

解決策(または同じことをする別の方法)

私はOPが述べたのとまったく同じ状況を経験しました。明らかに画面の下部にBottomNavigationViewがあり、その上にScrollViewがありました。

アクティビティでadjustPanを実行すると、キーボードが表示されてもスクロールが機能しないときに、BottomNavigationViewが一番下に残ります。

adjustResizeを実行するとスクロールは機能しますが、BottomNavigationViewはキーボードの上にプッシュされます。

以下では、同じことに対する2つのアプローチが考えられます。

アプローチ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_width="match_parent"
    Android:layout_height="match_parent">

    <Android.support.design.widget.AppBarLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content">

        <Android.support.v7.widget.Toolbar
            Android:id="@+id/toolbar"
            Android:layout_width="match_parent"
            Android:layout_height="?attr/actionBarSize"
            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_width="match_parent"
        Android:layout_height="match_parent"
        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_width="match_parent"
        Android:layout_height="wrap_content"
        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_で既に公開しています。 チェックしてください

それとは別に、キーボードの非表示/表示などでプログラムでslideUpまたはslideDownを呼び出すなど、いくつかの実験を試すことができます。

追伸私はこの完全に機能するアプローチにかなりの時間を費やしてきたので、誰かの時間を節約できるように、ここで共有することを考えました。

1
gprathour

マニフェストに次の行を追加します:Android:windowSoftInputMode = "adjustPan"

<activity
   Android:name=".main.MainActivity"
   Android:screenOrientation="portrait"
   Android:windowSoftInputMode="adjustPan" />
0

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値で変更されるということです。

0
nikis