Android当软键盘可见时,如何在全屏模式下调整布局

Android How to adjust layout in Full Screen Mode when softkeyboard is visible

当软键盘处于活动状态并且我已经成功实现它时,我已经研究了很多调整布局但是当我在清单文件中的活动标签中使用android:theme="@android:style/Theme.NoTitleBar.Fullscreen"时出现问题。

为此,我使用了android:windowSoftInputMode="adjustPan|adjustResize|stateHidden"不同的选项,但没有运气。

之后我以编程方式实现了FullScreen并尝试了各种布局来使用FullScreen,但都是徒劳的。

我引用了这些链接,并在此处查看了许多与此问题相关的帖子:

http://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.html

http://davidwparker.com/2011/08/30/android-how-to-float-a-row-above-keyboard/

这是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
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/masterContainerView"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="#ffffff">

    <ScrollView android:id="@+id/parentScrollView"
        android:layout_width="fill_parent" android:layout_height="wrap_content">

        <LinearLayout android:layout_width="fill_parent"
            android:layout_height="fill_parent" android:orientation="vertical">

            <TextView android:id="@+id/setup_txt" android:layout_width="wrap_content"
                android:layout_height="wrap_content" android:text="Setup - Step 1 of 3"
                android:textColor="@color/top_header_txt_color" android:textSize="20dp"
                android:padding="8dp" android:gravity="center_horizontal" />

            <TextView android:id="@+id/txt_header" android:layout_width="fill_parent"
                android:layout_height="40dp" android:text="AutoReply:"
                android:textColor="@color/top_header_txt_color" android:textSize="14dp"
                android:textStyle="bold" android:padding="10dp"
                android:layout_below="@+id/setup_txt" />

            <EditText android:id="@+id/edit_message"
                android:layout_width="fill_parent" android:layout_height="wrap_content"
                android:text="Some text here." android:textSize="16dp"
                android:textColor="@color/setting_editmsg_color" android:padding="10dp"
                android:minLines="5" android:maxLines="6" android:layout_below="@+id/txt_header"
                android:gravity="top" android:scrollbars="vertical"
                android:maxLength="132" />

            <ImageView android:id="@+id/image_bottom"
                android:layout_width="fill_parent" android:layout_height="wrap_content"
                android:layout_below="@+id/edit_message" />

        </LinearLayout>
    </ScrollView>

    <RelativeLayout android:id="@+id/scoringContainerView"
        android:layout_width="fill_parent" android:layout_height="50px"
        android:orientation="vertical" android:layout_alignParentBottom="true"
        android:background="#535254">

        <Button android:id="@+id/btn_save" android:layout_width="wrap_content"
            android:layout_height="wrap_content" android:layout_alignParentRight="true"
            android:layout_marginTop="7dp" android:layout_marginRight="15dp"
            android:layout_below="@+id/edit_message"
            android:text ="Save" />

        <Button android:id="@+id/btn_cancel" android:layout_width="wrap_content"
            android:layout_height="wrap_content" android:layout_marginTop="7dp"
            android:layout_marginRight="10dp" android:layout_below="@+id/edit_message"
            android:layout_toLeftOf="@+id/btn_save" android:text ="Cancel" />

    </RelativeLayout>
</RelativeLayout>

enter image description here

我希望当软键盘出现时,底部的2个按钮应该向上。

enter image description here


根据yghm的解决方法,我编写了一个便利类,允许我用一行代码解决问题(当然,在将新类添加到我的源代码之后)。单线是:

1
     AndroidBug5497Workaround.assistActivity(this);

实现类是:

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
public class AndroidBug5497Workaround {

    // For more information, see https://issuetracker.google.com/issues/36911528
    // To use this class, simply invoke assistActivity() on an Activity that already has its content view set.

    public static void assistActivity (Activity activity) {
        new AndroidBug5497Workaround(activity);
    }

    private View mChildOfContent;
    private int usableHeightPrevious;
    private FrameLayout.LayoutParams frameLayoutParams;

    private AndroidBug5497Workaround(Activity activity) {
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
        mChildOfContent = content.getChildAt(0);
        mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            public void onGlobalLayout() {
                possiblyResizeChildOfContent();
            }
        });
        frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
    }

    private void possiblyResizeChildOfContent() {
        int usableHeightNow = computeUsableHeight();
        if (usableHeightNow != usableHeightPrevious) {
            int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;
            if (heightDifference > (usableHeightSansKeyboard/4)) {
                // keyboard probably just became visible
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
            } else {
                // keyboard probably just became hidden
                frameLayoutParams.height = usableHeightSansKeyboard;
            }
            mChildOfContent.requestLayout();
            usableHeightPrevious = usableHeightNow;
        }
    }

    private int computeUsableHeight() {
        Rect r = new Rect();
        mChildOfContent.getWindowVisibleDisplayFrame(r);
        return (r.bottom - r.top);
    }
}

希望这有助于某人。


http://code.google.com/p/android/issues/list?can=2&q=fullscreen&colspec=ID+Type+Status+Owner+Summary+Stars&cells=tiles

- > http://code.google.com/p/android/issues/detail?id=5497&q=fullscreen&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars

- > https://groups.google.com/group/android-developers/msg/5690ac3a9819a53b?pli=1

- >全屏模式不调整大小


由于答案已经被挑选并且已知问题是一个错误,我想我会添加一个"可能的工作"。

显示软键盘时,您可以切换全屏模式。这允许"adjustPan"正常工作。

换句话说,我仍然使用@android:style / Theme.Black.NoTitleBar.Fullscreen作为应用程序主题的一部分,并将stateVisible | adjustResize作为活动窗口软输入模式的一部分但是要让它们一起工作我必须切换全屏模式在键盘出现之前。

使用以下代码:

关闭全屏模式

1
2
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

打开全屏模式

1
2
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);

注意 - 灵感来自:在全屏模式下隐藏标题


我尝试了约瑟夫约翰逊的解决方案,但与其他人一样,我遇到了内容与键盘之间的差距问题。出现此问题的原因是使用全屏模式时软输入模式始终为平移。当您激活将被软输入隐藏的输入字段时,此平移会干扰Joseph的解决方案。

当软输入出现时,首先根据其原始高度平移内容,然后按照Joseph解决方案请求的布局调整大小。调整大小和后续布局不会撤消平移,这会导致间隙。事件的完整顺序是:

  • 全局布局监听器
  • 摇摄
  • 内容布局(=实际调整内容大小)
  • 无法禁用平移,但可以通过更改内容的高度来强制平移偏移为0。这可以在侦听器中完成,因为它在平移发生之前运行。将内容高度设置为可用高度导致平滑的用户体验,即没有闪烁。

    我也做了这些改变。如果其中任何一个引入问题,请告诉我:

    • 切换确定可用高度getWindowVisibleDisplayFrame。缓存Rect以防止一点不需要的垃圾。
    • 也允许删除侦听器。当您为具有不同全屏要求的不同片段重用活动时,这非常有用。
    • 不要区分显示或隐藏的键盘,但始终将内容高度设置为可见的显示帧高度。

    它已经在Nexus 5上进行了测试,模拟器运行的API级别为16-24,屏幕尺寸从微小到大。

    代码已移植到Kotlin,但将我的更改移植回Java很简单。如果您需要帮助,请告诉我们:

    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
    class AndroidBug5497Workaround constructor(activity: Activity) {
        private val contentContainer = activity.findViewById(android.R.id.content) as ViewGroup
        private val rootView = contentContainer.getChildAt(0)
        private val rootViewLayout = rootView.layoutParams as FrameLayout.LayoutParams
        private val viewTreeObserver = rootView.viewTreeObserver
        private val listener = ViewTreeObserver.OnGlobalLayoutListener { possiblyResizeChildOfContent() }

        private val contentAreaOfWindowBounds = Rect()
        private var usableHeightPrevious = 0

        // I call this in"onResume()" of my fragment
        fun addListener() {
            viewTreeObserver.addOnGlobalLayoutListener(listener)
        }

        // I call this in"onPause()" of my fragment
        fun removeListener() {
            viewTreeObserver.removeOnGlobalLayoutListener(listener)
        }

        private fun possiblyResizeChildOfContent() {
            contentContainer.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds)
            val usableHeightNow = contentAreaOfWindowBounds.height()
            if (usableHeightNow != usableHeightPrevious) {
                rootViewLayout.height = usableHeightNow
                // Change the bounds of the root view to prevent gap between keyboard and content, and top of content positioned above top screen edge.
                rootView.layout(contentAreaOfWindowBounds.left, contentAreaOfWindowBounds.top, contentAreaOfWindowBounds.right, contentAreaOfWindowBounds.bottom)
                rootView.requestLayout()

                usableHeightPrevious = usableHeightNow
            }
        }
    }


    如果您使用系统UI方法(https://developer.android.com/training/system-ui/immersive.html),我刚刚找到了一个简单可靠的解决方案。

    它适用于使用View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN的情况,例如:如果您使用的是CoordinatorLayout

    它不适用于WindowManager.LayoutParams.FLAG_FULLSCREEN(您也可以使用android:windowFullscreen在主题中设置),但是您可以使用SYSTEM_UI_FLAG_LAYOUT_STABLE(根据文档"具有相同的视觉效果")实现类似的效果解决方案应该再次运作

    1
    2
    3
    getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION /* If you want to hide navigation */
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE)

    我在运行Marshmallow的设备上测试过它。

    关键是软键盘也是系统窗口之一(如状态栏和导航栏),因此系统发送的WindowInsets包含准确可靠的信息。

    对于DrawerLayout中的用例,我们试图在状态栏后面绘制,我们可以创建一个只忽略顶部插图的布局,并应用底部插图来考虑软键盘。

    这是我的自定义FrameLayout

    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
    /**
     * Implements an effect similar to {@code android:fitsSystemWindows="true"} on Lollipop or higher,
     * except ignoring the top system window inset. {@code android:fitsSystemWindows="true"} does not
     * and should not be set on this layout.
     */
    public class FitsSystemWindowsExceptTopFrameLayout extends FrameLayout {

        public FitsSystemWindowsExceptTopFrameLayout(Context context) {
            super(context);
        }

        public FitsSystemWindowsExceptTopFrameLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        public FitsSystemWindowsExceptTopFrameLayout(Context context, AttributeSet attrs,
                                                     int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }

        @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
        public FitsSystemWindowsExceptTopFrameLayout(Context context, AttributeSet attrs,
                                                     int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }

        @Override
        public WindowInsets onApplyWindowInsets(WindowInsets insets) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                setPadding(insets.getSystemWindowInsetLeft(), 0, insets.getSystemWindowInsetRight(),
                        insets.getSystemWindowInsetBottom());
                return insets.replaceSystemWindowInsets(0, insets.getSystemWindowInsetTop(), 0, 0);
            } else {
                return super.onApplyWindowInsets(insets);
            }
        }
    }

    并使用它:

    1
    2
    3
    4
    5
    6
    7
    <com.example.yourapplication.FitsSystemWindowsExceptTopFrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!-- Your original layout here -->
    </com.example.yourapplication.FitsSystemWindowsExceptTopFrameLayout>

    理论上,这应该适用于任何没有疯狂修改的设备,比任何试图采用随机1/31/4屏幕尺寸作为参考的黑客要好得多。

    (它需要API 16+,但我只在Lollipop +上使用全屏来绘制状态栏,因此在这种情况下它是最佳解决方案。)


    我也不得不面对这个问题并且有一个工作我在HTC one,galaxy s1,s2,s3,note和HTC感觉上检查。

    在布局的根视图上放置一个全局布局侦听器

    1
    2
    3
    4
    5
    mRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener(){
                public void onGlobalLayout() {
                    checkHeightDifference();
                }
        });

    在那里我检查了高度差,如果屏幕的高度差大于屏幕高度的三分之一,那么我们可以假设键盘是打开的。
    从这个答案中得到了它。

    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
    private void checkHeightDifference(){
        // get screen frame rectangle
        Rect r = new Rect();
        mRootView.getWindowVisibleDisplayFrame(r);
        // get screen height
        int screenHeight = mRootView.getRootView().getHeight();
        // calculate the height difference
        int heightDifference = screenHeight - (r.bottom - r.top);

        // if height difference is different then the last height difference and
        // is bigger then a third of the screen we can assume the keyboard is open
        if (heightDifference > screenHeight/3 && heightDifference != mLastHeightDifferece) {
            // keyboard visiblevisible
            // get root view layout params
            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mRootView.getLayoutParams();
            // set the root view height to screen height minus the height difference
            lp.height = screenHeight - heightDifference;
            // call request layout so the changes will take affect
            .requestLayout();
            // save the height difference so we will run this code only when a change occurs.
            mLastHeightDifferece = heightDifference;
        } else if (heightDifference != mLastHeightDifferece) {
            // keyboard hidden
            PFLog.d("[ChatroomActivity] checkHeightDifference keyboard hidden");
            // get root view layout params and reset all the changes we have made when the keyboard opened.
            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mRootView.getLayoutParams();
            lp.height = screenHeight;
            // call request layout so the changes will take affect
            mRootView.requestLayout();
            // save the height difference so we will run this code only when a change occurs.
            mLastHeightDifferece = heightDifference;
        }
    }

    这可能不是防弹,也许在某些设备上它不起作用,但它对我有用,并希望它也会帮助你。


    请注意,当为活动设置WindowManager.LayoutParams.FLAG_FULLSCREEN时,android:windowSoftInputMode="adjustResize"不起作用。你有两个选择。

  • 为您的活动禁用全屏模式。在全屏模式下不会调整活动的大小。您可以在xml中(通过更改活动的主题)或在Java代码中执行此操作。在onCreate()方法中添加以下行。

    1
    2
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);  
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);`
  • 要么

  • 使用另一种方法来实现全屏模式。在onCreate()方法中添加以下代码。

    1
    2
    3
    4
    5
    6
    7
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
    View decorView = getWindow().getDecorView();
    // Hide the status bar.
    int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
    decorView.setSystemUiVisibility(uiOptions);`
  • 请注意,方法2仅适用于Android 4.1及更高版本。


    我实施了Joseph Johnson解决方案并且运行良好,我注意到在使用此解决方案后,应用程序上的抽屉有时无法正常关闭。
    我添加了一个功能,当用户关闭edittexts所在的片段时,删除侦听器removeOnGlobalLayoutListener。

    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
        //when the application uses full screen theme and the keyboard is shown the content not scrollable!
    //with this util it will be scrollable once again
    //http://stackoverflow.com/questions/7417123/android-how-to-adjust-layout-in-full-screen-mode-when-softkeyboard-is-visible
    public class AndroidBug5497Workaround {


        private static AndroidBug5497Workaround mInstance = null;
        private View mChildOfContent;
        private int usableHeightPrevious;
        private FrameLayout.LayoutParams frameLayoutParams;
        private ViewTreeObserver.OnGlobalLayoutListener _globalListener;

        // For more information, see https://code.google.com/p/android/issues/detail?id=5497
        // To use this class, simply invoke assistActivity() on an Activity that already has its content view set.

        public static AndroidBug5497Workaround getInstance (Activity activity) {
            if(mInstance==null)
            {
                synchronized (AndroidBug5497Workaround.class)
                {
                    mInstance = new AndroidBug5497Workaround(activity);
                }
            }
            return mInstance;
        }

        private AndroidBug5497Workaround(Activity activity) {
            FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
            mChildOfContent = content.getChildAt(0);
            frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();

            _globalListener = new ViewTreeObserver.OnGlobalLayoutListener()
            {

                @Override
                public void onGlobalLayout()
                {
                     possiblyResizeChildOfContent();
                }
            };
        }

        public void setListener()
        {
             mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(_globalListener);
        }

        public void removeListener()
        {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                mChildOfContent.getViewTreeObserver().removeOnGlobalLayoutListener(_globalListener);
            } else {
                mChildOfContent.getViewTreeObserver().removeGlobalOnLayoutListener(_globalListener);
            }
        }

        private void possiblyResizeChildOfContent() {
            int usableHeightNow = computeUsableHeight();
            if (usableHeightNow != usableHeightPrevious) {
                int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
                int heightDifference = usableHeightSansKeyboard - usableHeightNow;
                if (heightDifference > (usableHeightSansKeyboard/4)) {
                    // keyboard probably just became visible
                    frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
                } else {
                    // keyboard probably just became hidden
                    frameLayoutParams.height = usableHeightSansKeyboard;
                }
                mChildOfContent.requestLayout();
                usableHeightPrevious = usableHeightNow;
            }
        }

        private int computeUsableHeight() {
            Rect r = new Rect();
            mChildOfContent.getWindowVisibleDisplayFrame(r);
            return (r.bottom - r.top);
        }
    }

    使用我的edittexts所在的类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Override
    public void onStart()
    {
        super.onStart();
        AndroidBug5497Workaround.getInstance(getActivity()).setListener();
    }

    @Override
    public void onStop()
    {
        super.onStop();
        AndroidBug5497Workaround.getInstance(getActivity()).removeListener();
    }

    android:fitsSystemWindows="true"添加到布局中,此布局将调整大小。


    要使其与FullScreen一起使用:

    使用离子键盘插件。这使您可以在键盘出现和消失时进行监听。

    OnDeviceReady添加这些事件侦听器:

    1
    2
    3
    4
    // Allow Screen to Move Up when Keyboard is Present
    window.addEventListener('native.keyboardshow', onKeyboardShow);
    // Reset Screen after Keyboard hides
    window.addEventListener('native.keyboardhide', onKeyboardHide);

    逻辑:

    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
    function onKeyboardShow(e) {
        // Get Focused Element
        var thisElement = $(':focus');
        // Get input size
        var i = thisElement.height();
        // Get Window Height
        var h = $(window).height()
        // Get Keyboard Height
        var kH = e.keyboardHeight
        // Get Focused Element Top Offset
        var eH = thisElement.offset().top;
        // Top of Input should still be visible (30 = Fixed Header)
        var vS = h - kH;
        i = i > vS ? (vS - 30) : i;
        // Get Difference
        var diff = (vS - eH - i);
        if (diff < 0) {
            var parent = $('.myOuter-xs.myOuter-md');
            // Add Padding
            var marginTop = parseInt(parent.css('marginTop')) + diff - 25;
            parent.css('marginTop', marginTop + 'px');
        }
    }

    function onKeyboardHide(e) {
      // Remove All Style Attributes from Parent Div
      $('.myOuter-xs.myOuter-md').removeAttr('style');
    }

    基本上,如果它们的差异为负,则表示键盘覆盖输入的像素数量。因此,如果你调整你的父div,应该抵消它。

    向逻辑添加超时300毫秒也应该优化性能(因为这将允许键盘时间出现。


    我尝试了约瑟夫约翰逊的课程,虽然有效,但并不能满足我的需求。而不是模仿android:windowSoftInputMode ="adjustResize",我需要模拟android:windowSoftInputMode ="adjustPan"。

    我正在使用它来进行全屏webview。要将内容视图平移到正确的位置,我需要使用一个javascript界面??,它提供有焦点的页面元素位置的详细信息,从而接收键盘输入。我已经省略了这些细节,但是我重写了约瑟夫约翰逊的课程。它将为您提供一个非常可靠的基础,以实现自定义泛与其调整大小。

    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
    package some.package.name;

    import some.package.name.JavaScriptObject;

    import android.app.Activity;
    import android.graphics.Rect;
    import android.view.View;
    import android.view.ViewTreeObserver;
    import android.widget.FrameLayout;

    //-------------------------------------------------------
    // ActivityPanner Class
    //
    // Convenience class to handle Activity attributes bug.
    // Use this class instead of windowSoftInputMode="adjustPan".
    //
    // To implement, call enable() and pass a reference
    // to an Activity which already has its content view set.
    // Example:
    //      setContentView( R.layout.someview );
    //      ActivityPanner.enable( this );
    //-------------------------------------------------------
    //
    // Notes:
    //
    // The standard method for handling screen panning
    // when the virtual keyboard appears is to set an activity
    // attribute in the manifest.
    // Example:
    // <activity
    //      ...
    //      android:windowSoftInputMode="adjustPan"
    //      ... >
    // Unfortunately, this is ignored when using the fullscreen attribute:
    //      android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
    //
    //-------------------------------------------------------
    public class ActivityPanner {

        private View contentView_;
        private int priorVisibleHeight_;

        public static void enable( Activity activity ) {
            new ActivityPanner( activity );
        }

        private ActivityPanner( Activity activity ) {
            FrameLayout content = (FrameLayout)
                activity.findViewById( android.R.id.content );
            contentView_ = content.getChildAt( 0 );
            contentView_.getViewTreeObserver().addOnGlobalLayoutListener(
                new ViewTreeObserver.OnGlobalLayoutListener() {
                    public void onGlobalLayout() { panAsNeeded(); }
            });
        }

        private void panAsNeeded() {

            // Get current visible height
            int currentVisibleHeight = visibleHeight();

            // Determine if visible height changed
            if( currentVisibleHeight != priorVisibleHeight_ ) {

                // Determine if keyboard visiblity changed
                int screenHeight =
                    contentView_.getRootView().getHeight();
                int coveredHeight =
                    screenHeight - currentVisibleHeight;
                if( coveredHeight > (screenHeight/4) ) {
                    // Keyboard probably just became visible

                    // Get the current focus elements top & bottom
                    // using a ratio to convert the values
                    // to the native scale.
                    float ratio = (float) screenHeight / viewPortHeight();
                    int elTop = focusElementTop( ratio );
                    int elBottom = focusElementBottom( ratio );

                    // Determine the amount of the focus element covered
                    // by the keyboard
                    int elPixelsCovered = elBottom - currentVisibleHeight;

                    // If any amount is covered
                    if( elPixelsCovered > 0 ) {

                        // Pan by the amount of coverage
                        int panUpPixels = elPixelsCovered;

                        // Prevent panning so much the top of the element
                        // becomes hidden
                        panUpPixels = ( panUpPixels > elTop ?
                                        elTop : panUpPixels );

                        // Prevent panning more than the keyboard height
                        // (which produces an empty gap in the screen)
                        panUpPixels = ( panUpPixels > coveredHeight ?
                                        coveredHeight : panUpPixels );

                        // Pan up
                        contentView_.setY( -panUpPixels );
                    }
                }
                else {
                    // Keyboard probably just became hidden

                    // Reset pan
                    contentView_.setY( 0 );
                }

                // Save usabale height for the next comparison
                priorVisibleHeight_ = currentVisibleHeight;
            }
        }

        private int visibleHeight() {
            Rect r = new Rect();
            contentView_.getWindowVisibleDisplayFrame( r );
            return r.bottom - r.top;
        }

        // Customize this as needed...
        private int viewPortHeight() { return JavaScriptObject.viewPortHeight(); }
        private int focusElementTop( final float ratio ) {
            return (int) (ratio * JavaScriptObject.focusElementTop());
        }
        private int focusElementBottom( final float ratio ) {
            return (int) (ratio * JavaScriptObject.focusElementBottom());
        }

    }


    保持android:windowSoftInputMode="adjustResize"。因为它只保留"adjustResize""adjustPan"中的一个(窗口调整模式是用adjustResize或adjustPan指定的。强烈建议您始终指定一个或另一个)。你可以在这里找到它:
    http://developer.android.com/resources/articles/on-screen-inputs.html

    它对我来说很完美。


    实际上,无论我在FullScreen模式中选择什么windowSoftInputMode,软键盘外观似乎都不会以任何方式影响Activity

    虽然我找不到很多关于这个属性的文档,但我认为FullScreen模式是专为游戏应用而设计的,不需要太多使用软键盘。如果您的活动需要用户通过软键盘进行交互,请使用非FullScreen主题重新考虑。您可以使用NoTitleBar主题关闭TitleBar。为什么要隐藏通知栏?


    我目前正在使用这种方法,它就像一个魅力。诀窍是我们从上面和下面21的不同方法获得键盘高度,然后在我们的活动中将它用作我们根视图的底部填充。我假设您的布局不需要顶部填充(在状态栏下方),但如果您这样做,请通知我更新我的答案。

    MainActivity.java

    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
    public class MainActivity extends AppCompatActivity {
        @Override
        protected void onCreate(final Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            RelativeLayout mainLayout = findViewById(R.id.main_layout);

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                ViewCompat.setOnApplyWindowInsetsListener(mainLayout , new OnApplyWindowInsetsListener() {
                    @Override
                    public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
                        v.setPadding(0, 0, 0, insets.getSystemWindowInsetBottom());
                        return insets;
                    }
                });
            } else {
                View decorView = getWindow().getDecorView();
                final View contentView = mainLayout;
                decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        Rect r = new Rect();
                        //r will be populated with the coordinates of your view that area still visible.
                        decorView.getWindowVisibleDisplayFrame(r);

                        //get screen height and calculate the difference with the useable area from the r
                        int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
                        int diff = height - r.bottom;

                        //if it could be a keyboard add the padding to the view
                        if (diff != 0) {
                            // if the use-able screen height differs from the total screen height we assume that it shows a keyboard now
                            //check if the padding is 0 (if yes set the padding for the keyboard)
                            if (contentView.getPaddingBottom() != diff) {
                                //set the padding of the contentView for the keyboard
                                contentView.setPadding(0, 0, 0, diff);
                            }
                        } else {
                            //check if the padding is != 0 (if yes reset the padding)
                            if (contentView.getPaddingBottom() != 0) {
                                //reset the padding of the contentView
                                contentView.setPadding(0, 0, 0, 0);
                            }
                        }
                    }
                });
            }
        }
    ...
    }

    不要忘记使用id来解决根视图:

    activity_main.xml中

    1
    2
    3
    4
    5
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/main_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    希望它可以帮助某人。


    I used Joseph Johnson created AndroidBug5497Workaround class but getting black space between softkeyboard and the view. I referred this link Greg Ennis. After doing some changes to the above this is my final working code.

    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
     public class SignUpActivity extends Activity {

     private RelativeLayout rlRootView; // this is my root layout
     private View rootView;
     private ViewGroup contentContainer;
     private ViewTreeObserver viewTreeObserver;
     private ViewTreeObserver.OnGlobalLayoutListener listener;
     private Rect contentAreaOfWindowBounds = new Rect();
     private FrameLayout.LayoutParams rootViewLayout;
     private int usableHeightPrevious = 0;

     private View mDecorView;

     @Override
     protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_sign_up);
      mDecorView = getWindow().getDecorView();
      contentContainer =
       (ViewGroup) this.findViewById(android.R.id.content);

      listener = new OnGlobalLayoutListener() {
       @Override
       public void onGlobalLayout() {
        possiblyResizeChildOfContent();
       }
      };

      rootView = contentContainer.getChildAt(0);
      rootViewLayout = (FrameLayout.LayoutParams)
      rootView.getLayoutParams();

      rlRootView = (RelativeLayout) findViewById(R.id.rlRootView);


      rlRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
       @Override
       public void onGlobalLayout() {
        int heightDiff = rlRootView.getRootView().getHeight() - rlRootView.getHeight();
        if (heightDiff > Util.dpToPx(SignUpActivity.this, 200)) {
         // if more than 200 dp, it's probably a keyboard...
         //  Logger.info("Soft Key Board","Key board is open");

        } else {
         Logger.info("Soft Key Board","Key board is CLOSED");

         hideSystemUI();
        }
       }
      });
     }

     // This snippet hides the system bars.
     protected void hideSystemUI() {
      // Set the IMMERSIVE flag.
      // Set the content to appear under the system bars so that the
      content
      // doesn't resize when the system bars hide and show.
      mDecorView.setSystemUiVisibility(
       View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
     }
     @Override
     protected void onPause() {
      super.onPause();
      if (viewTreeObserver.isAlive()) {
       viewTreeObserver.removeOnGlobalLayoutListener(listener);
      }
     }

     @Override
     protected void onResume() {
      super.onResume();
      if (viewTreeObserver == null || !viewTreeObserver.isAlive()) {
       viewTreeObserver = rootView.getViewTreeObserver();
      }
      viewTreeObserver.addOnGlobalLayoutListener(listener);
     }

     @Override
     protected void onDestroy() {
      super.onDestroy();
      rootView = null;
      contentContainer = null;
      viewTreeObserver = null;
     }
     private void possiblyResizeChildOfContent() {
      contentContainer.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds);

      int usableHeightNow = contentAreaOfWindowBounds.height();

      if (usableHeightNow != usableHeightPrevious) {
       rootViewLayout.height = usableHeightNow;
       rootView.layout(contentAreaOfWindowBounds.left,
        contentAreaOfWindowBounds.top, contentAreaOfWindowBounds.right, contentAreaOfWindowBounds.bottom);
       rootView.requestLayout();

       usableHeightPrevious = usableHeightNow;
      } else {

       this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
      }
     }
    }

    基于https://stackoverflow.com/a/19494006/1815624并希望实现这一目标......

    更新的想法

    结合答案

    • https://stackoverflow.com/a/19494006/1815624
    • https://stackoverflow.com/a/10952394/1815624

    相关代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
            if (heightDifference > (usableHeightSansKeyboard / 4)) {

                // keyboard probably just became visible
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
                activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
            } else {

                // keyboard probably just became hidden
                if(usableHeightPrevious != 0) {
                    frameLayoutParams.height = usableHeightSansKeyboard;
                    activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
                    activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

                }

    完整资料来源:https://github.com/CrandellWS/AndroidBug5497Workaround/blob/master/AndroidBug5497Workaround.java

    老想法

    在打开键盘之前创建容器高度的静态值
    键盘打开时根据usableHeightSansKeyboard - heightDifference设置容器高度,并在关闭时将其设置回保存的值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    if (heightDifference > (usableHeightSansKeyboard / 4)) {
                    // keyboard probably just became visible
                    frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
                    int mStatusHeight = getStatusBarHeight();
                    frameLayoutParams.topMargin = mStatusHeight;
                    ((MainActivity)activity).setMyMainHeight(usableHeightSansKeyboard - heightDifference);

                    if(BuildConfig.DEBUG){
                        Log.v("aBug5497","keyboard probably just became visible");
                    }
                } else {
                    // keyboard probably just became hidden
                    if(usableHeightPrevious != 0) {
                        frameLayoutParams.height = usableHeightSansKeyboard;
                        ((MainActivity)activity).setMyMainHeight();    
                    }
                    frameLayoutParams.topMargin = 0;

                    if(BuildConfig.DEBUG){
                        Log.v("aBug5497","keyboard probably just became hidden");
                    }
                }

    MainActivity中的方法

    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
    public void setMyMainHeight(final int myMainHeight) {

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                ConstraintLayout.LayoutParams rLparams =  (ConstraintLayout.LayoutParams) myContainer.getLayoutParams();
                rLparams.height = myMainHeight;

                myContainer.setLayoutParams(rLparams);
            }

        });

    }

    int mainHeight = 0;
    public void setMyMainHeight() {

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                ConstraintLayout.LayoutParams rLparams =  (ConstraintLayout.LayoutParams) myContainer.getLayoutParams();
                rLparams.height = mainHeight;

                myContainer.setLayoutParams(rLparams);
            }

        });

    }

    示例容器XML

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <android.support.constraint.ConstraintLayout
        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.constraint.ConstraintLayout
                android:id="@+id/my_container"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                app:layout_constraintHeight_percent=".8">

    如果需要,可以添加类似的利润......

    另一个考虑因素是使用填充,可以在以下位置找到此示例:

    https://github.com/mikepenz/MaterialDrawer/issues/95#issuecomment-80519589


    在使用AdjustPan时仅使用android:windowSoftInputMode="adjustResize|stateHidden,然后禁用调整大小属性


    您希望底栏粘在视图的底部,但是当显示键盘时,它们应向上移动以放置在键盘上方,对吧?

    您可以尝试以下代码段:

    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
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        ...>

        <RelativeLayout
            android:id="@+id/RelativeLayoutTopBar"
        ...>
        </RelativeLayout>

        <LinearLayout
            android:id="@+id/LinearLayoutBottomBar"
            android:layout_alignParentBottom = true
            ...>
        </LinearLayout>

        <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="390dp"
        android:orientation="vertical"
        android:layout_above="@+id/LinearLayoutBottomBar"
        android:layout_below="@+id/RelativeLayoutTopBar">

        <ScrollView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:id="@+id/ScrollViewBackground">

                ...

            </ScrollView>
         </LinearLayout>
      </RelativeLayout>

    BottomBar将粘贴到视图的底部,包含ScrollView的LinearLayout将在顶部/底部栏和键盘显示后占据视图的左侧。如果它对您有用,请告诉我。


    我只是使用全屏模式来隐藏状态栏。但是,我希望应用程序在显示键盘时调整大小。所有其他解决方案(可能由于帖子的年龄)都很复杂或不可能(我希望避免更改Java代码以解决PhoneGap Build的问题)。

    我没有使用全屏,而是将我的Android配置修改为非全屏:

    1
                [cc]

    并通过命令行添加cordova-plugin-statusbar

    1
    cordova plugin add cordova-plugin-statusbar

    当应用程序加载后,我简单地调用插件上的方法来隐藏自己,如:

    1
    2
        if (window.cordova && window.cordova.platformId == 'android' && window.StatusBar)
            window.StatusBar.hide();

    这就像一个魅力。唯一真正的缺点是,当应用程序加载时,状态栏是明显可见的。根据我的需要,这不是问题。


    不要使用:

    1
    2
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

    因为工作不好。
    而不是那样,使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    fun setFullScreen(fullScreen: Boolean) {
            val decorView = getWindow().getDecorView()
            val uiOptions : Int
            if(fullScreen){
                uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN // this hide statusBar
                toolbar.visibility = View.GONE // if you use toolbar
                tabs.visibility = View.GONE // if you use tabLayout
            } else {
                uiOptions = View.SYSTEM_UI_FLAG_VISIBLE // this show statusBar
                toolbar.visibility = View.VISIBLE
                tabs.visibility = View.VISIBLE
            }
            decorView.setSystemUiVisibility(uiOptions)
        }

    我已经尝试了stackOverflow的所有可能的答案,最后我在一周的长搜索后解决了。
    我使用了坐标布局,我用linearLayout更改了它,我的问题得到了解决。我不知道坐标布局可能有错误或任何我的错误。


    我尝试了很多解决方案,包括Joseph Johnson和Johan Stuyts。但结果是,在所有情况下,我在某些设备(如联想s820)上的内容和键盘之间都有一个空白区域。
    所以我对他们的代码做了一些修改,最后得到了解决方案。

    我的想法是基于在键盘显示时为内容添加边距。

    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
    contentContainer.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds);
        int usableHeightNow = contentAreaOfWindowBounds.height();

        if (usableHeightNow != usableHeightPrevious) {

            int difference = usableHeightNow - usableHeightPrevious;

            if (difference < 0 && difference < -150) {
                keyboardShowed = true;
                rootViewLayout.topMargin -= difference + 30;
                rootViewLayout.bottomMargin += 30;
            }
            else if (difference < 0 && difference > -150){
                rootViewLayout.topMargin -= difference + 30;
            }
            else if (difference > 0 && difference > 150) {
                keyboardShowed = false;
                rootViewLayout.topMargin = 0;
                rootViewLayout.bottomMargin = 0;
            }

            rootView.requestLayout();

            Log.e("Bug Workaround","Difference:" + difference);

            usableHeightPrevious = usableHeightNow;
    }

    正如您所看到的,我添加了30 px差异,因为屏幕顶部和内容区域之间有一个小的空白区域。而且我不知道它从哪里出现所以我决定将边距缩小,现在它正是我需要的。


    1)创建KeyboardHeightHelper:

    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
    public class KeyboardHeightHelper {

        private final View decorView;
        private int lastKeyboardHeight = -1;

        public KeyboardHeightHelper(Activity activity, View activityRootView, OnKeyboardHeightChangeListener listener) {
            this.decorView = activity.getWindow().getDecorView();
            activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
                int keyboardHeight = getKeyboardHeight();
                if (lastKeyboardHeight != keyboardHeight) {
                    lastKeyboardHeight = keyboardHeight;
                    listener.onKeyboardHeightChange(keyboardHeight);
                }
            });
        }

        private int getKeyboardHeight() {
            Rect rect = new Rect();
            decorView.getWindowVisibleDisplayFrame(rect);
            return decorView.getHeight() - rect.bottom;
        }

        public interface OnKeyboardHeightChangeListener {
            void onKeyboardHeightChange(int keyboardHeight);
        }
    }

    2)让您的活动全屏:

    activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

    3)监听键盘高度变化并为视图添加底部填充:

    1
    2
    3
    4
    5
    View rootView = activity.findViewById(R.id.root); // your root view or any other you want to resize
    KeyboardHeightHelper effectiveHeightHelper = new KeyboardHeightHelper(
            activity,
            rootView,
            keyboardHeight -> rootView.setPadding(0, 0, 0, keyboardHeight));

    因此,每次键盘都会出现在屏幕上 - 视图的底部填充将发生变化,内容将重新排列。


    今天没有工作adjustResize全屏问题是实际的Android sdk。

    从我找到的答案:
    解决方案 - 但解决方案显示图片问题:
    >
</p>
<p>
比我找到解决方案并删除一个不必要的行动:
</p>
<div class=

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

    所以,请参阅我在Kotlin上的固定解决方案代码:

    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
    class AndroidBug5497Workaround constructor(val activity: Activity) {

        private val content = activity.findViewById<View>(android.R.id.content) as FrameLayout

        private val mChildOfContent = content.getChildAt(0)
        private var usableHeightPrevious: Int = 0
        private val contentContainer = activity.findViewById(android.R.id.content) as ViewGroup
        private val rootView = contentContainer.getChildAt(0)
        private val rootViewLayout = rootView.layoutParams as FrameLayout.LayoutParams

        private val listener = {
            possiblyResizeChildOfContent()
        }

        fun addListener() {
            mChildOfContent.apply {
                viewTreeObserver.addOnGlobalLayoutListener(listener)

            }
        }

        fun removeListener() {
            mChildOfContent.apply {
                viewTreeObserver.removeOnGlobalLayoutListener(listener)
            }
        }

        private fun possiblyResizeChildOfContent() {
            val contentAreaOfWindowBounds = Rect()
            mChildOfContent.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds)
            val usableHeightNow = contentAreaOfWindowBounds.height()

            if (usableHeightNow != usableHeightPrevious) {
                rootViewLayout.height = usableHeightNow
                rootView.layout(contentAreaOfWindowBounds.left,
                        contentAreaOfWindowBounds.top, contentAreaOfWindowBounds.right, contentAreaOfWindowBounds.bottom);
                mChildOfContent.requestLayout()
                usableHeightPrevious = usableHeightNow
            }
        }
    }

    我的bug修复工具代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     class LeaveDetailActivity : BaseActivity(){

        private val keyBoardBugWorkaround by lazy {
            AndroidBug5497Workaround(this)
        }

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)

        }

        override fun onResume() {
            keyBoardBugWorkaround.addListener()
            super.onResume()
        }

        override fun onPause() {
            keyBoardBugWorkaround.removeListener()
            super.onPause()
        }
    }


    谢谢约瑟夫的回答。但是,在方法possibleResizeChildOfContent()中,该部分

    1
    2
    3
    4
    else {
                // keyboard probably just became hidden
                frameLayoutParams.height = usableHeightSansKeyboard;
            }

    因为视图的下半部分被隐藏起来,所以对我不起作用。
    所以我不得不采用全局变量restoreHeight,并在构造函数中插入最后一行

    1
    restoreHeight = frameLayoutParams.height;

    然后我替换了前面提到的部分

    1
    2
    3
    4
    else {
                // keyboard probably just became hidden
                frameLayoutParams.height = restoreHeight;
            }

    但我不知道为什么你的代码不适合我。如果有人能够阐明这一点,那将会有很大的帮助。


    就我而言,一旦我将Crosswalk添加到我的Cordova应用程序中,这个问题就开始发生了。我的应用程序未在全屏和android中使用:windowSoftInputMode ="adjustPan"。

    我已经在应用程序中使用了离子键盘插件,因此检测键盘是上升还是下降很容易归功于它:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // Listen for events to when the keyboard is opened and closed
    window.addEventListener("native.keyboardshow", keyboardUp, false);
    window.addEventListener('native.keyboardhide', keyboardDown, false);

    function keyboardUp()
    {
        $('html').addClass('keyboardUp');
    }

    function keyboardDown()
    {
        $('html').removeClass('keyboardUp');
    }

    我尝试了上面的所有修复,但最终为我做的简单线是这个css:

    1
    2
    3
    &.keyboardUp {
            overflow-y: scroll;
    }

    希望这能节省你花在这上面的几天。 :)