关于android:软键盘出现时如何调整布局

How to adjust layout when soft keyboard appears

我想在软键盘激活时调整/重新调整布局大小,如下所示:

之前和之后:

enter image description here enter image description here

在SO中找到了几个资源:

  • 如何在显示软键盘时保持所有字段和文本可见
  • android软键盘出现时会破坏布局
  • 软键盘打开时调整布局
  • 但问题& 答案是相当模糊的,这里的问题是我想要的更清晰的画面。

    要求:

    • 它应该适用于任何屏幕尺寸的手机。
    • 注意到"FACEBOOK"和"注册"中的边距/填充空间
      Facebook"前后发生了变化。
    • 不涉及滚动视图。


    只需添加

    1
    android:windowSoftInputMode="adjustResize"

    在AndroidManifest.xml中,您声明此特定活动,这将调整布局调整大小选项。

    enter image description here

    下面的一些源代码用于布局设计

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="20dp"
            android:text="FaceBook"
            android:textAppearance="?android:attr/textAppearanceLarge" />

        <EditText
            android:id="@+id/editText1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/textView1"
            android:layout_marginTop="30dp"
            android:ems="10"
            android:hint="username">

            <requestFocus />
        </EditText>

        <EditText
            android:id="@+id/editText2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/editText1"
            android:layout_marginTop="20dp"
            android:ems="10"
            android:hint="password" />

        <Button
            android:id="@+id/button1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/editText2"
            android:layout_centerHorizontal="true"
            android:layout_marginLeft="18dp"
            android:layout_marginTop="20dp"
            android:text="Log In" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_marginTop="17dp"
            android:gravity="center"
            android:text="Sign up for facebook"
            android:textAppearance="?android:attr/textAppearanceLarge" />

    </RelativeLayout>


    几年前问了这个问题,"秘密Andro Geni"有一个很好的基础解释,"tir38"也对完整的解决方案做了很好的尝试,但是这里没有完整的解决方案。
    我花了几个小时搞清楚事情,这是我的完整解决方案,底部有详细解释:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    <?xml version="1.0" encoding="utf-8"?>
    <ScrollView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="10dp">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_above="@+id/mainLayout"
                android:layout_alignParentTop="true"
                android:id="@+id/headerLayout">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:gravity="center_horizontal">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:id="@+id/textView1"
                        android:text="facebook"
                        android:textStyle="bold"
                        android:ellipsize="marquee"
                        android:singleLine="true"
                        android:textAppearance="?android:attr/textAppearanceLarge" />

                </LinearLayout>

            </RelativeLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:id="@+id/mainLayout"
                android:orientation="vertical">

                <EditText
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:id="@+id/editText1"
                    android:ems="10"
                    android:hint="Email or Phone"
                    android:inputType="textVisiblePassword">

                    <requestFocus />
                </EditText>

                <EditText
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="10dp"
                    android:id="@+id/editText2"
                    android:ems="10"
                    android:hint="Password"
                    android:inputType="textPassword" />

                <Button
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="10dp"
                    android:id="@+id/button1"
                    android:text="Log In"
                    android:onClick="login" />

            </LinearLayout>

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_below="@+id/mainLayout"
                android:id="@+id/footerLayout">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_alignParentBottom="true">

                    <RelativeLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content">

                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:id="@+id/textView2"
                            android:text="Sign Up for Facebook"
                            android:layout_centerHorizontal="true"
                            android:layout_alignBottom="@+id/helpButton"
                            android:ellipsize="marquee"
                            android:singleLine="true"
                            android:textAppearance="?android:attr/textAppearanceSmall" />

                        <Button
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_alignParentRight="true"
                            android:id="@+id/helpButton"
                            android:text="\?"
                            android:onClick="help" />

                    </RelativeLayout>

                </LinearLayout>

            </RelativeLayout>

        </RelativeLayout>

    </ScrollView>

    在AndroidManifest.xml中,不要忘记设置:

    1
    android:windowSoftInputMode="adjustResize"

    标签上,您想要这样的布局。

    思考:

    我已经意识到RelativeLayout是跨越所有可用空间的布局,然后在键盘弹出时调整大小。

    并且LinearLayout是在调整大小过程中不会调整大小的布局。

    这就是为什么你需要在ScrollView之后立即使用1 RelativeLayout来跨越所有可用的屏幕空间。你需要在RelativeLayout内部有一个LinearLayout,否则你的内部会在调整大小时被压碎。好的例子是"headerLayout"。如果RelativeLayout内没有LinearLayout,那么RelativeLayout"facebook"文本会被粉碎而无法显示。

    在问题中发布的"facebook"登录图片中我也注意到整个登录部分(mainLayout)相对于整个屏幕是垂直居中的,因此属性:

    1
    android:layout_centerVertical="true"

    LinearLayout布局上。并且因为mainLayout位于LinearLayout内,这意味着该部分不会调整大小(再次查看相关图片)。


    在您的Manifest中添加此行,您的Activity将被调用

    1
    android:windowSoftInputMode="adjustPan|adjustResize"

    要么

    你可以在onCreate中添加这一行

    1
    getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE|WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);


    Android Developer有正确的答案,但提供的源代码非常冗长,并没有实际实现图中描述的模式。

    这是一个更好的模板:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    <?xml version="1.0" encoding="utf-8"?>
    <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fillViewport="true">

        <RelativeLayout android:layout_width="match_parent"
                        android:layout_height="match_parent">

            <LinearLayout android:layout_width="match_parent"
                          android:layout_height="wrap_content"
                          android:orientation="vertical">

                    <!-- stuff to scroll -->

            </LinearLayout>

            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true">

                <!-- footer -->

            </FrameLayout>

        </RelativeLayout>

    </ScrollView>

    由您自己决定用于"滚动"和"页脚"部分的视图。也知道你可能需要设置ScrollView
    fillViewPort。


    它可以适用于所有类型的布局。

  • 将其添加到AndroidManifest.xml中的activity标记中
  • android:windowSoftInputMode="adjustResize"

    例如:

    1
    2
    3
    4
    <activity android:name=".ActivityLogin"
        android:screenOrientation="portrait"
        android:theme="@style/AppThemeTransparent"
        android:windowSoftInputMode="adjustResize"/>
  • 将它添加到activitypage.xml中的布局标记上,该标记将更改其位置。
  • android:fitsSystemWindows="true"

    android:layout_alignParentBottom="true"

    例如:

    1
    2
    3
    4
    5
    <RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:fitsSystemWindows="true">


    这使得可以显示先前由键盘隐藏的任何所需布局。

    将其添加到AndroidManifest.xml中的activity标记中

    android:windowSoftInputMode="adjustResize"



    使用ScrollView环绕根视图,最好使用scrollbars = none。除了用于解决此问题之外,ScrollView将不会使用您的布局更改任何内容。

    然后在要在键盘上方完全显示的视图上设置fitsSystemWindows ="true"。
    这将使您的EditText在键盘上方可见,并且可以向下滚动到EditText下方的部分,但在视图中使用fitsSystemWindows ="true"。

    android:fitsSystemWindows="true"

    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="none">

        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:fitsSystemWindows="true">

            ...

        </android.support.constraint.ConstraintLayout>
    </ScrollView>

    如果要在键盘出现的那一刻显示键盘上方的fitsSystemWindows ="true"视图的完整部分,则需要一些代码将视图滚动到底部:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    // Code is in Kotlin

    setupKeyboardListener(scrollView) // call in OnCreate or similar


    private fun setupKeyboardListener(view: View) {
        view.viewTreeObserver.addOnGlobalLayoutListener {
            val r = Rect()
            view.getWindowVisibleDisplayFrame(r)
            if (Math.abs(view.rootView.height - (r.bottom - r.top)) > 100) { // if more than 100 pixels, its probably a keyboard...
                onKeyboardShow()
            }
        }
    }

    private fun onKeyboardShow() {
        scrollView.scrollToBottomWithoutFocusChange()
    }

    fun ScrollView.scrollToBottomWithoutFocusChange() { // Kotlin extension to scrollView
        val lastChild = getChildAt(childCount - 1)
        val bottom = lastChild.bottom + paddingBottom
        val delta = bottom - (scrollY + height)
        smoothScrollBy(0, delta)
    }

    完整布局示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        <RelativeLayout
            android:id="@+id/statisticsLayout"
            android:layout_width="match_parent"
            android:layout_height="340dp"
            android:background="@drawable/some"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <ImageView
                android:id="@+id/logoImageView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="64dp"
                android:src="@drawable/some"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/authenticationLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginEnd="32dp"
            android:layout_marginStart="32dp"
            android:layout_marginTop="20dp"
            android:focusableInTouchMode="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/statisticsLayout">

            <android.support.design.widget.TextInputLayout
                android:id="@+id/usernameEditTextInputLayout"
                android:layout_width="match_parent"
                android:layout_height="68dp">

                <EditText
                    android:id="@+id/usernameEditText"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />

            </android.support.design.widget.TextInputLayout>

            <android.support.design.widget.TextInputLayout
                android:id="@+id/passwordEditTextInputLayout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/usernameEditTextInputLayout">

                <EditText
                    android:id="@+id/passwordEditText"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />

            </android.support.design.widget.TextInputLayout>

            <Button
                android:id="@+id/loginButton"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/passwordEditTextInputLayout"
                android:layout_centerHorizontal="true"
                android:layout_marginBottom="10dp"
                android:layout_marginTop="20dp" />

            <Button
                android:id="@+id/forgotPasswordButton"
                android:layout_width="wrap_content"
                android:layout_height="40dp"
                android:layout_below="@id/loginButton"
                android:layout_centerHorizontal="true" />

        </RelativeLayout>

    </android.support.constraint.ConstraintLayout>


    很多答案都是对的。在AndroidManifest我写道:

    1
    2
    3
    4
    5
    <activity
        android:name=".SomeActivity"
        android:configChanges="orientation|keyboardHidden|screenSize" // Optional, doesn't affect.
        android:theme="@style/AppTheme.NoActionBar"
        android:windowSoftInputMode="adjustResize" />

    在我的情况下,我在styles.xml中添加了一个主题,但您可以使用自己的主题:

    1
    2
    3
    4
    5
    <style name="AppTheme.NoActionBar" parent="AppTheme">
        <!--  Hide ActionBar -->
        <item name="windowNoTitle">true</item>
        <item name="windowActionBar">false</item>
    </style>

    我注意到,如果我使用全屏主题,则不会调整大小:

    1
    2
    3
    4
    5
    6
    7
    <style name="AppTheme.FullScreenTheme" parent="AppTheme">
        <!--  Hide ActionBar -->
        <item name="windowNoTitle">true</item>
        <item name="windowActionBar">false</item>
        <!--  Hide StatusBar -->
        <item name="android:windowFullscreen">true</item>
    </style>

    同样在我的情况下adjustResize有效,但adjustPan没有。

    有关全屏布局,请参阅Android中的解决方法当软键盘可见时,或者在https://gist.github.com/grennis/2e3cd5f7a9238c59861015ce0a7c5584中,如何在全屏模式下调整布局。

    另外https://medium.com/@sandeeptengale/problem-solved-3-android-full-screen-view-translucent-scrollview-adjustresize-keyboard-b0547c7ced32有效,但它的StatusBar是透明的,所以电池,时钟,Wi- Fi图标可见。

    如果使用"文件">"新建">"活动">"全屏活动"创建活动,则使用代码:

    1
    2
    3
    4
    5
    6
    7
    fullscreen_content.systemUiVisibility =
        View.SYSTEM_UI_FLAG_LOW_PROFILE or
        View.SYSTEM_UI_FLAG_FULLSCREEN or
        View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
        View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
        View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
        View.SYSTEM_UI_FLAG_HIDE_NAVIGATION

    你也不会取得成果。您可以在根容器中使用android:fitsSystemWindows="true",但会出现StatusBar。因此,请使用第一个链接中的变通方法。


    您只需在AndroidManifest.xml文件中设置这些选项即可。

    1
    2
    3
    <activity
        android:name=".YourACtivityName"
        android:windowSoftInputMode="stateVisible|adjustResize">

    Google不建议使用adjustPan,因为用户可能需要关闭键盘才能看到所有输入字段。

    更多信息:Android App Manifest


    在我看来,它有所帮助。

    main_layout.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_main2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        android:orientation="vertical"
        tools:context="com.livewallpaper.profileview.loginact.Main2Activity">

    <TextView
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:text="Title"
        android:gravity="center"
        android:layout_height="0dp" />
    <LinearLayout
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="0dp">
        <EditText
            android:hint="enter here"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
    <TextView
        android:layout_weight="1"
        android:text="signup for App"
        android:gravity="bottom|center_horizontal"
        android:layout_width="match_parent"
        android:layout_height="0dp" />
    </LinearLayout>

    manifest文件中使用它

    1
    2
    3
    <activity android:name=".MainActivity"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="adjustResize"/>

    现在最重要的部分!
    ActivityApplication标记中使用这样的主题。

    1
    android:theme="@style/AppTheme"

    主题就是这样的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <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="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="windowActionModeOverlay">true</item>
    </style>

    所以我错过了这个主题。这让我整天感到沮丧。


    对于使用ConstraintLayout的用户,android:windowSoftInputMode="adjustPan|adjustResize"将无效。

    您可以做的是使用软键盘监听器,从上部视图的底部到底部设置视图的约束,然后为每个视图(作为约束之间的位置百分比)设置垂直偏差到水平指南(也按百分比定位) ,但对于父母)。

    对于每个视图,我们只需要在显示键盘时将app:layout_constraintBottom_toBottomOf更改为@+id/guideline,当然是以编程方式。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
            <ImageView
            android:id="@+id/loginLogo"
            ...
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.15" />


            <RelativeLayout
            android:id="@+id/loginFields"
            ...
            app:layout_constraintVertical_bias=".15"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/loginLogo">

            <Button
            android:id="@+id/login_btn"
            ...
            app:layout_constraintVertical_bias=".25"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/loginFields"/>

    通常,软键盘占用的屏幕高度不超过50%。因此,您可以将指南设置为0.5。

    1
    2
    3
    4
    5
    6
            <android.support.constraint.Guideline
            android:id="@+id/guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.5"/>

    现在以编程方式,当键盘未显示时,我们可以将所有app:layout_constraintBottom_toBottomOf设置回父级,反之亦然。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
                unregistrar = KeyboardVisibilityEvent.registerEventListener(this, isOpen -> {
                loginLayout.startAnimation(AnimationManager.getFade(200));
                if (isOpen) {
                    setSoftKeyViewParams(loginLogo, R.id.guideline, ConstraintLayout.LayoutParams.PARENT_ID, -1,"235:64", 0.15f,
                            63, 0, 63, 0);
                    setSoftKeyViewParams(loginFields, R.id.guideline, -1, R.id.loginLogo, null, 0.15f,
                            32, 0, 32, 0);
                    setSoftKeyViewParams(loginBtn, R.id.guideline, -1, R.id.useFingerPrintIdText, null, 0.5f,
                            32, 0, 32, 0);
                } else {
                    setSoftKeyViewParams(loginLogo, ConstraintLayout.LayoutParams.PARENT_ID, ConstraintLayout.LayoutParams.PARENT_ID, -1,"235:64", 0.15f,
                            63, 0, 63, 0);
                    setSoftKeyViewParams(loginFields, ConstraintLayout.LayoutParams.PARENT_ID, -1, R.id.loginLogo,null, 0.15f,
                            32, 0, 32, 0);
                    setSoftKeyViewParams(loginBtn, ConstraintLayout.LayoutParams.PARENT_ID, -1, R.id.useFingerPrintIdText,null, 0.25f,
                            32, 0, 32, 0);
                }
            });

    调用此方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
        private void setSoftKeyViewParams(View view, int bottomToBottom, int topToTop, int topToBottom, String ratio, float verticalBias,
                                      int left, int top, int right, int bottom) {
        ConstraintLayout.LayoutParams viewParams = new ConstraintLayout.LayoutParams(view.getLayoutParams().width, view.getLayoutParams().height);
        viewParams.dimensionRatio = ratio;
        viewParams.bottomToBottom = bottomToBottom;
        viewParams.topToTop = topToTop;
        viewParams.topToBottom = topToBottom;
        viewParams.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID;
        viewParams.startToStart = ConstraintLayout.LayoutParams.PARENT_ID;
        viewParams.verticalBias = verticalBias;
        viewParams.setMargins(Dimensions.dpToPx(left), Dimensions.dpToPx(top), Dimensions.dpToPx(right), Dimensions.dpToPx(bottom));
        view.setLayoutParams(viewParams);
    }

    重要的是确保在键盘显示和未显示时能够正确缩放的方式设置垂直偏置。


    我使用这个扩展类框架
    当我需要重新计算高度大小onLayout时,我会覆盖onmeasure
    并使用getKeyboardHeight()减去keyboardHeight

    我的创建框架需要使用软键盘调整大小

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    SizeNotifierFrameLayout frameLayout = new SizeNotifierFrameLayout(context) {
                private boolean first = true;

                @Override
                protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
                    super.onLayout(changed, left, top, right, bottom);

                    if (changed) {
                        fixLayoutInternal(first);
                        first = false;
                    }
                }

                @Override
                protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                    super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec) - getKeyboardHeight(), MeasureSpec.EXACTLY));
                }

                @Override
                protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
                    boolean result = super.drawChild(canvas, child, drawingTime);
                    if (child == actionBar) {
                        parentLayout.drawHeaderShadow(canvas, actionBar.getMeasuredHeight());
                    }
                    return result;
                }


            };

    SizeNotifierFrameLayout

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    public class SizeNotifierFrameLayout extends FrameLayout {

        public interface SizeNotifierFrameLayoutDelegate {
            void onSizeChanged(int keyboardHeight, boolean isWidthGreater);
        }

        private Rect                            rect            = new Rect();
        private Drawable                        backgroundDrawable;
        private int                             keyboardHeight;
        private int                             bottomClip;
        private SizeNotifierFrameLayoutDelegate delegate;
        private boolean                         occupyStatusBar = true;

        public SizeNotifierFrameLayout(Context context) {
            super(context);
            setWillNotDraw(false);
        }

        public Drawable getBackgroundImage() {
            return backgroundDrawable;
        }

        public void setBackgroundImage(Drawable bitmap) {
            backgroundDrawable = bitmap;
            invalidate();
        }

        public int getKeyboardHeight() {
            View rootView = getRootView();
            getWindowVisibleDisplayFrame(rect);
            int usableViewHeight = rootView.getHeight() - (rect.top != 0 ? AndroidUtilities.statusBarHeight : 0) - AndroidUtilities.getViewInset(rootView);
            return usableViewHeight - (rect.bottom - rect.top);
        }

        public void notifyHeightChanged() {
            if (delegate != null) {
                keyboardHeight = getKeyboardHeight();
                final boolean isWidthGreater = AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y;
                post(new Runnable() {
                    @Override
                    public void run() {
                        if (delegate != null) {
                            delegate.onSizeChanged(keyboardHeight, isWidthGreater);
                        }
                    }
                });
            }
        }

        public void setBottomClip(int value) {
            bottomClip = value;
        }

        public void setDelegate(SizeNotifierFrameLayoutDelegate delegate) {
            this.delegate = delegate;
        }

        public void setOccupyStatusBar(boolean value) {
            occupyStatusBar = value;
        }

        protected boolean isActionBarVisible() {
            return true;
        }

        @Override
        protected void onDraw(Canvas canvas) {
            if (backgroundDrawable != null) {
                if (backgroundDrawable instanceof ColorDrawable) {
                    if (bottomClip != 0) {
                        canvas.save();
                        canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight() - bottomClip);
                    }
                    backgroundDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
                    backgroundDrawable.draw(canvas);
                    if (bottomClip != 0) {
                        canvas.restore();
                    }
                } else if (backgroundDrawable instanceof BitmapDrawable) {
                    BitmapDrawable bitmapDrawable = (BitmapDrawable) backgroundDrawable;
                    if (bitmapDrawable.getTileModeX() == Shader.TileMode.REPEAT) {
                        canvas.save();
                        float scale = 2.0f / AndroidUtilities.density;
                        canvas.scale(scale, scale);
                        backgroundDrawable.setBounds(0, 0, (int) Math.ceil(getMeasuredWidth() / scale), (int) Math.ceil(getMeasuredHeight() / scale));
                        backgroundDrawable.draw(canvas);
                        canvas.restore();
                    } else {
                        int actionBarHeight =
                                (isActionBarVisible() ? ActionBar.getCurrentActionBarHeight() : 0) + (Build.VERSION.SDK_INT >= 21 && occupyStatusBar ? AndroidUtilities.statusBarHeight : 0);
                        int   viewHeight = getMeasuredHeight() - actionBarHeight;
                        float scaleX     = (float) getMeasuredWidth() / (float) backgroundDrawable.getIntrinsicWidth();
                        float scaleY     = (float) (viewHeight + keyboardHeight) / (float) backgroundDrawable.getIntrinsicHeight();
                        float scale      = scaleX < scaleY ? scaleY : scaleX;
                        int   width      = (int) Math.ceil(backgroundDrawable.getIntrinsicWidth() * scale);
                        int   height     = (int) Math.ceil(backgroundDrawable.getIntrinsicHeight() * scale);
                        int   x          = (getMeasuredWidth() - width) / 2;
                        int   y          = (viewHeight - height + keyboardHeight) / 2 + actionBarHeight;
                        canvas.save();
                        canvas.clipRect(0, actionBarHeight, width, getMeasuredHeight() - bottomClip);
                        backgroundDrawable.setBounds(x, y, x + width, y + height);
                        backgroundDrawable.draw(canvas);
                        canvas.restore();
                    }
                }
            } else {
                super.onDraw(canvas);
            }
        }

        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            super.onLayout(changed, l, t, r, b);
            notifyHeightChanged();
        }
    }


    对我来说,它适用于这行代码:

    1
    getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

    只需将其放入onCreate方法即可。
    最好!


    将此行添加到Manifiest文件中:

    1
    android:windowSoftInputMode="adjustResize"

    这段代码适合我。键盘出现时,您可以滚动屏幕


    在AndroidManifest.xml中

    1
    2
    3
    4
    <activity android:name=".signup.screen_2.SignUpNameAndPasswordActivity"
                      android:screenOrientation="portrait"
                      android:windowSoftInputMode="adjustResize">
    </activity>

    activity_sign_up.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    <?xml version="1.0" encoding="utf-8"?>
    <ScrollView
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true"
            tools:context=".signup.screen_2.SignUpNameAndPasswordActivity">
        <LinearLayout
                android:fitsSystemWindows="true"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

            <LinearLayout
                    android:layout_marginTop="@dimen/dp_24"
                    android:layout_marginStart="@dimen/dp_24"
                    android:layout_marginEnd="@dimen/dp_24"
                    android:id="@+id/lin_name_password"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical">

                <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_horizontal"
                        android:fontFamily="sans-serif-medium"
                        android:text="@string/name_and_password"
                        android:textColor="@color/colorBlack"
                        android:layout_marginTop="@dimen/dp_5"
                        android:textSize="@dimen/ts_16"/>

                <EditText
                        android:id="@+id/edit_full_name"
                        android:layout_width="match_parent"
                        android:layout_height="@dimen/dp_44"
                        app:layout_constraintTop_toTopOf="parent"
                        android:hint="@string/email_address_hint"
                        android:inputType="textPersonName"
                        android:imeOptions="flagNoFullscreen"
                        android:textSize="@dimen/ts_15"
                        android:background="@drawable/rounded_border_edittext"
                        android:layout_marginTop="@dimen/dp_15"
                        android:paddingStart="@dimen/dp_8"
                        android:paddingEnd="@dimen/dp_8"
                        android:maxLength="100"
                        android:maxLines="1"/>

                <EditText
                        android:id="@+id/edit_password"
                        android:layout_width="match_parent"
                        android:layout_height="@dimen/dp_44"
                        app:layout_constraintTop_toTopOf="parent"
                        android:hint="@string/password"
                        android:inputType="textPassword"
                        android:imeOptions="flagNoFullscreen"
                        android:textSize="@dimen/ts_15"
                        android:background="@drawable/rounded_border_edittext"
                        android:layout_marginTop="@dimen/dp_15"
                        android:paddingStart="@dimen/dp_8"
                        android:paddingEnd="@dimen/dp_8"
                        android:maxLength="100"
                        android:maxLines="1"/>

                <TextView
                        android:id="@+id/btn_continue_and_sync_contacts"
                        android:layout_width="match_parent"
                        android:layout_height="@dimen/dp_44"
                        android:gravity="center"
                        android:clickable="true"
                        android:focusable="true"
                        android:layout_marginTop="@dimen/dp_15"
                        android:background="@drawable/btn_blue_selector"
                        android:enabled="false"
                        android:text="@string/continue_and_sync_contacts"
                        android:textColor="@color/colorWhite"
                        android:textSize="@dimen/ts_15"
                        android:textStyle="bold"/>

                <TextView
                        android:id="@+id/btn_continue_without_syncing_contacts"
                        android:layout_width="match_parent"
                        android:layout_height="@dimen/dp_44"
                        android:gravity="center"
                        android:clickable="true"
                        android:focusable="true"
                        android:layout_marginTop="@dimen/dp_10"
                        android:enabled="false"
                        android:text="@string/continue_without_syncing_contacts"
                        android:textColor="@color/colorBlue"
                        android:textSize="@dimen/ts_15"
                        android:textStyle="bold"/>

            </LinearLayout>
            <!--RelativeLayout is scaled when keyboard appears-->
            <RelativeLayout
                    android:layout_marginStart="@dimen/dp_24"
                    android:layout_marginEnd="@dimen/dp_24"
                    android:layout_marginBottom="@dimen/dp_20"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent">

                <LinearLayout
                        android:layout_alignParentBottom="true"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:orientation="vertical">
                    <TextView
                            android:id="@+id/tv_learn_more_1"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:clickable="true"
                            android:focusable="true"
                            android:layout_gravity="center_horizontal"
                            android:text="@string/learn_more_syncing_contacts"
                            android:textColor="@color/black_alpha_70"
                            android:gravity="center"
                            android:layout_marginBottom="1dp"
                            android:textSize="@dimen/ts_13"/>

                    <TextView
                            android:id="@+id/tv_learn_more_2"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:clickable="true"
                            android:focusable="true"
                            android:layout_gravity="center_horizontal"
                            android:text="@string/learn_more"
                            android:fontFamily="sans-serif-medium"
                            android:textColor="@color/black_alpha_70"
                            android:textSize="@dimen/ts_13"/>
                </LinearLayout>
            </RelativeLayout>
        </LinearLayout>
    </ScrollView>

    rounded_border_edittext.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_activated="true">
            <shape android:shape="rectangle">
                <solid android:color="#F6F6F6"/>
                <corners android:radius="3dp"/>
                <stroke
                        android:width="1dp"
                        android:color="@color/red"/>
            </shape>
        </item>
        <item android:state_activated="false">
            <shape android:shape="rectangle">
                <solid android:color="#F6F6F6"/>
                <corners android:radius="3dp"/>
                <stroke
                        android:width="1dp"
                        android:color="@color/colorGray"/>
            </shape>
        </item>
    </selector>

    btn_blue_selector.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_enabled="true" android:state_pressed="true">
            <shape android:shape="rectangle">
                <corners android:radius="3dp"/>
                <solid android:color="@color/colorBlueLight"/>
                <stroke android:width="1dp" android:color="@color/colorBlueLight"/>
            </shape>
        </item>
        <item android:state_enabled="true">
            <shape android:shape="rectangle">
                <corners android:radius="3dp"/>
                <solid android:color="@color/colorBlue"/>
                <stroke android:width="1dp" android:color="@color/colorBlue"/>
            </shape>
        </item>
        <item android:state_enabled="false">
            <shape android:shape="rectangle">
                <corners android:radius="3dp"/>
                <solid android:color="@color/colorBlueAlpha"/>
                <stroke android:width="0dp" android:color="@color/colorBlueAlpha"/>
            </shape>
        </item>
    </selector>