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


178

当软键盘处于活动状态时,我已经进行了很多研究来调整布局,并且我已经成功实现了它,但是当我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代码:

<?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>

在此处输入图片说明

我希望当软键盘进入图片时,底部的2个按钮应向上移动。

在此处输入图片说明


1
我认为您必须在ScrollView内和EditText下面添加Button。
Balaji Khadake 2011年

我已经尝试了许多不起作用的选项...
Vineet Shukla

1
放入的FrameLayout乌尔按钮和FrameLayout里的权重设置为1,最后只用android:windowSoftInputMode="adjustPan"告诉我,如果这项工作..
谢里夫elKhatib

@VineetShukla您找到全屏显示的作品了吗?
Muhammad Babar

2
请注意,你不应该使用adjustResize,并adjustPan在同一时间,从的Javadoc android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE:“这不能与{@link SOFT_INPUT_ADJUST_PAN}相结合”
丹尼斯Kniazhev

Answers:


257

基于yghm的变通方法,我编写了一个便捷类,该类使我可以单线解决问题(当然,在将新类添加到我的源代码之后)。单线是:

     AndroidBug5497Workaround.assistActivity(this);

实现类是:


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);
    }
}

希望这对某人有帮助。


8
谢谢!我不知道为什么,但我不得不更换return (r.bottom - r.top);return r.bottom得到它在我的HTC One迷你的工作,否则,活动视图将通过状态栏的大小过高推。我还没有在其他设备上对其进行测试。希望能对您有所帮助。
2014年

4
嗨,约瑟夫·约翰逊,我使用了您的代码,它运行良好。但是,如今在某些小型设备上面临着一个问题,即它显示出键盘和布局之间的间隙(黑屏)。您对这个问题有任何想法吗?我也尝试过返回r.bottom。
Pankaj 2014年

2
约瑟夫·约翰逊(Joseph Johnson):我实现了您的方法,当我们单击顶部的编辑文本时,它的工作正常,但是当我们单击底部的编辑文本时,所有设计都
在进行

3
不幸的是,它不适用于Nexus 7(2013)。即使在不设置adjustNothing的情况下,它仍然可以平移。
Le-roy Staines 2014年

4
很棒的答案,非常感谢。它可以在Nexus 6上运行,但是 如果我不这样做,frameLayoutParams.height = usableHeightSansKeyboard;则不得不使用frameLayoutParams.height = usableHeightNow;某些元素而不是屏幕上的其他元素。
罗伯托·阿连德'16

36

由于答案已经被选择并且已知问题是错误,所以我认为我将添加“可能的解决方法”。

显示软键盘时,您可以切换全屏模式。这样可以使“ adjustPan”正常工作。

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

使用以下代码:

关闭全屏模式

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

开启全萤幕模式

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

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


1
多谢您拨出时间解决问题,为此+1。我一定会测试这种方法,并让您知道它是否对我有用,谢谢。
Vineet Shukla 2012年

1
正在怀疑中工作!真的很好的解决方案!从我身边+1。
迈克


键盘会卡住,使键盘背景变黑。捕捉效果不好看:(
nibz

哇感谢...它结合了变通办法中提到的AndroidBug5497Workaround对我的作品真的很好...我上传的合并源GitHub上... github.com/CrandellWS/AndroidBug5497Workaround/blob/master/...
CrandellWS

23

我尝试了约瑟夫·约翰逊Joseph Johnson)解决方案,但是像其他人一样,我遇到了内容与键盘之间的鸿沟。发生此问题的原因是,在使用全屏模式时,软输入模式始终处于平移状态。当您激活将由软输入隐藏的输入字段时,此平移会干扰Joseph的解决方案。

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

  1. 全局布局侦听器
  2. 平移
  3. 内容的布局(=实际调整内容的大小)

无法禁用平移,但是可以通过更改内容的高度将平移偏移强制为0。可以在侦听器中完成此操作,因为它是在平移发生之前运行的。将内容高度设置为可用高度可带来流畅的用户体验,即不会闪烁。

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

  • 切换确定可用高度getWindowVisibleDisplayFrame。该Rect缓存,以防止不必要的垃圾一点点。
  • 也允许删除侦听器。当您将活动重用于具有不同全屏要求的不同片段时,此功能很有用。
  • 不要区分显示的键盘还是隐藏的键盘,但始终将内容高度设置为可见的显示框架高度。

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

该代码已被移植到Kotlin,但是将所做的更改移植回Java很简单。让我知道您是否需要帮助:

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
        }
    }
}

9
这似乎是最好的答案。我在这里gist.github.com/grennis/2e3cd5f7a9238c59861015ce0a7c5584移植到Java 。请注意,我发现观察者还活着,但也必须对其进行检查。
格雷格·恩尼斯

哦,我的上帝!遍历所有系统视图层次结构以查找该Ghost空间。我快要把一台食品卡车的电脑扔掉了,但在最后一分钟看到了你的答案。它有效:)
rupps

1
@Greg Ennis感谢您的Java端口。节省了大量的精力和时间。
伊坤18'Apr

@GregEnnis,谢谢,您的解决方案适用于onResume(),onPause(),onDestroy()(请参阅GitHub代码中的注释)。
CoolMind '18 -10-17

这对我来说是有效的,除了removeListener调用似乎不起作用。我在possiblyResizeChildOfContent通话和removeListener通话中都添加了removeListener断点,即使在达到断点之后,possiblyResizeChildOfContent仍会被调用。还有谁有相同的问题吗?
奎因,

14

如果您正在使用系统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根据docs “具有相同的视觉效果” ),并且该解决方案应该可以再次使用。

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)

我已经在运行棉花糖的设备上对其进行了测试。

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

对于诸如 DrawerLayout试图在状态栏后面绘制,我们可以创建仅忽略顶部插图的布局,并应用底部插图来说明软键盘。

这是我的习惯FrameLayout

/**
 * 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);
        }
    }
}

并使用它:

<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 +上使用全屏显示状态栏,因此在这种情况下,这是最好的解决方案。)


@Dilip只要满足上述条件,它就可以在API 16+上运行。
张海

10

请注意,为某项活动设置android:windowSoftInputMode="adjustResize"时该功能不起作用WindowManager.LayoutParams.FLAG_FULLSCREEN您有两个选择。

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

    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);   
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);`

要么

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

    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);`

请注意,method-2仅适用于Android 4.1及更高版本。


@AnshulTyagi method-2仅适用于Android 4.1及更高版本。
Abhinav Chauhan

4
Nexus 9和Samsung s4分别在5.0和4.4.2上进行了测试,第二种方法无效。
RobVoisey

1
第二种方法根本行不通,我浪费了很多时间。
格雷格·恩尼斯

谢谢,保存我的一天。
Deni Rohimat

9

我也不得不面对这个问题,并且进行了一些工作,检查了HTC One,S1,S2,S3,银河和HTC的感觉。

将全局布局侦听器放在布局的根视图上

mRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener(){
            public void onGlobalLayout() {
                checkHeightDifference();
            }
    });

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

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;
    }
}

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


1
需要进行一些调整,但是可以。在Nexus 7 2013中,我不得不将键盘高度(screenHeight / 3)减小了一些像素。好主意,谢谢!
Joao Sousa 2013年

7

我实现了约瑟夫·约翰逊(Joseph Johnson)解决方案,并且运行良好,我注意到使用该解决方案后,有时应用程序上的抽屉无法正确关闭。我添加了一项功能,当用户关闭片段所在的编辑文本时,删除监听器removeOnGlobalLayoutListener。

    //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);
    } 
}

使用我的edittext所在的类

@Override
public void onStart()
{
    super.onStart();
    AndroidBug5497Workaround.getInstance(getActivity()).setListener();
}

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

7

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


那就是为我解决的。此外,请确保将其设置在正确的视图上。如果您的背景应该位于状态栏下方,请不要在此处设置背景,而应在内部布局上。可能EditText视图等应该位于第二个布局内部。另请观看此演讲,因为它使事情变得更清楚:youtube.com/watch?v=_mGDMVRO3iE
Stan,

也为我工作。感谢@Stan评论,我还能够使其与FULLSCREEN主题一起使用,从而将该属性放置在ViewPager而不是活动/片段布局上。
marcouberti

5

要使其与FullScreen一起使用,请执行以下操作:

使用离子键盘插件。这使您可以侦听键盘的出现和消失时间。

OnDeviceReady添加以下事件侦听器:

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

逻辑:

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,则应该抵消它。

将超时添加到逻辑中表示300ms也应该优化性能(因为这将使键盘时间出现。


3

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

我正在使用它进行全屏webview。为了将内容视图平移到正确的位置,我需要使用一个javascript接口,该接口提供有关具有焦点的页面元素的位置的详细信息,因此正在接收键盘输入。我已经省略了这些细节,但是提供了对约瑟夫·约翰逊课的重写。这将为您实现自定义平移与调整其大小提供坚实的基础。

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());
    }

}

似乎正是我所需要的,请您提供完整的样品?感谢您的工作!
vilicvane 2015年

我不想发布整个项目。尽管提供了完善的解决方案,但我提供的内容将带给您很长的路要走。您需要定义的内容:创建一个“ JavaScriptObject”类,并将其作为js界面注入到Webview中(有关此信息,请参阅Webview文档)。如果编写的内容使用WebView的方式全面,那么您很有可能已经做到了。在Web视图中添加JavaScript,以侦听焦点事件并将有关焦点元素定位的数据馈入JavaScriptObject类。
BuvinJ

2

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

尽管我找不到有关此属性的大量文档,但我认为该FullScreen模式是为游戏应用程序设计的,不需要大量使用软键盘。如果您的活动是需要用户通过软键盘进行交互的活动,请重新考虑使用非全屏主题。您可以使用NoTitleBar主题关闭TitleBar 。您为什么要隐藏通知栏?


2

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

它非常适合我。


我没有任何问题...我也尝试过您的XML。这也适用于..m,使用的是OS版本2.2
Balaji Khadake 2011年

我仅尝试使用全屏模式...正在Nexus One和Nexus S上对其进行测试...。
Balaji Khadake

1
我曾尝试过Galaxy S,HTC野火,HTC Hero,摩托罗拉Deify和Sony XPeria。在任何单个设备上均不起作用。
Vineet Shukla


1

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


我也用过它。...请让您以全屏模式进行操作,并且要在哪台设备上进行测试?
Vineet Shukla

HTC NEXUS一,确定要全屏显示
Mohammed Azharuddin Shaikh

你可以使用getWindow()。requestFeature(Window.FEATURE_NO_TITLE); onCreate()而不是使用主题?
Mohammed Azharuddin Shaikh

10
上面的代码可以在没有全屏的情况下正常工作,但是可以从xml或代码中添加全屏...这是行不通的...请仔细阅读问题。
Vineet Shukla

1

我使用约瑟夫·约翰逊(Joseph Johnson)创建的AndroidBug5497Workaround类,但在软键盘和视图之间却留有空白。我引用了此链接Greg Ennis。对上述内容进行一些更改后,这是我的最终工作代码。

 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);
  }
 }
}

1

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

MainActivity.java

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

<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">

希望它能帮助某人。


1

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

更新的想法


结合来自

相关代码:

        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键盘打开的时间设置容器高度,并在关闭时将其设置回保存的值

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中的方法

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

<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


1

1)创建KeyboardHeightHelper:

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)聆听键盘高度的变化并为视图添加底部填充:

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));

因此,每次键盘出现在屏幕上时-视图底部的填充将更改,并且内容将重新排列。


0

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

您可以尝试以下代码片段:

<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将在显示顶部/底部栏和键盘之后采用视图的剩余内容。让我知道它是否也适合您。


1
非常奇怪,因为它多次在我的应用程序中工作。顺便说一下,R​​elativeLayout没有方向,因此您可以在代码中删除这些属性。我刚刚意识到我可以将代码段削减到这一行:android:layout_below =“ @ + id / scoringContainerView”,您必须将其添加到ScrollView
banzai86'9

全屏?您是说没有顶部的布局吗?
banzai86 2011年

不.....我的意思是没有状态栏显示电池寿命,设备的连接性等..
Vineet Shukla

不,状态栏在我的应用中可见。您是否可以尝试更改布局的顺序,这意味着您在其他代码上方使用按钮放置了布局代码,然后重试?也许您必须先定义它们才能使用layout_below
banzai86 2011年

1
请仔细阅读问题……我已经提到我在全屏模式下遇到了麻烦……
Vineet Shukla

0

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

else {
            // keyboard probably just became hidden
            frameLayoutParams.height = usableHeightSansKeyboard;
        }

对我来说不起作用,因为下部的视野被隐藏了。所以我必须使用全局变量restoreHeight,然后在构造函数中插入最后一行

restoreHeight = frameLayoutParams.height;

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

else {
            // keyboard probably just became hidden
            frameLayoutParams.height = restoreHeight;
        }

但是我不知道为什么您的代码对我不起作用。如果有人可以阐明这一点,那将有很大的帮助。


0

我只使用全屏模式来隐藏状态栏。但是,我希望在显示键盘时调整应用程序的大小。所有其他解决方案(可能是由于发布时间的原因)都很复杂,或者我无法使用(希望避免更改JavaG代码以免除PhoneGap Build的使用)。

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

            <preference name="fullscreen" value="false" />

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

cordova plugin add cordova-plugin-statusbar

应用加载后,我可以简单地在插件上调用方法来隐藏自身,例如:

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

这就像一个魅力。唯一真正的缺点是,在加载应用程序时状态栏会短暂可见。对于我的需求,这不是问题。


0

我已经尝试了stackOverflow的所有可能答案,终于经过一周的长时间搜索终于解决了。我使用了坐标布局,并使用linearLayout更改了此布局,问题已解决。我不知道坐标布局可能有错误或任何我的错误。


0

我尝试了许多解决方案,包括约瑟夫·约翰逊(Joseph Johnson)和约翰·斯图伊特(Johan Stuyts)。但是结果是,在所有情况下,某些设备(例如Lenovo s820)在内容和键盘之间都留有空白。因此,我对他们的代码进行了一些更改,终于找到了可行的解决方案。

我的想法基于在显示键盘时在内容顶部增加边距。

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像素添加到差异中,因为在屏幕顶部和带有边距的内容区域之间有一个小的空白。而且我不知道它出现的位置,所以我决定只是缩小边距,现在它完全可以按照我的需要工作了。


0

今天,在全屏问题上,adjustResize无法正常工作对于android sdk来说是实际的。

从我发现的答案中:
解决方案 -但是解决方案在图片上显示了此问题:

比我找到解决方案并删除了一项不必要的操作:

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

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

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
        }
    }
}

我的错误修复工具代码:

 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()
    }
}

0

不要使用:

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

因为效果不好。而不是使用:

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)
    }

-1

就我而言,将Crosswalk添加到Cordova应用程序后,便开始出现此问题。我的应用未在全屏和android:windowSoftInputMode =“ adjustPan”中使用。

我已经在应用程序中安装了离子键盘插件,因此,借助它,可以轻松检测键盘是向上还是向下:

// 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');
}

我尝试了上面的所有修复程序,但最终为我完成的操作很简单:

&.keyboardUp {
        overflow-y: scroll;
}

希望这可以节省您我花了几天的时间。:)


我正在使用科尔多瓦人行横道以及android:windowSoftInputMode =“ adjustPan”。但是,它不起作用。我看到该类已添加到html元素中,但是css在屏幕上没有任何作用。您还有其他设置可以让屏幕移动吗?
darewreck

我必须设置添加transform:translateY(0px)使其工作。但是,滚动根本不起作用。有任何想法吗?
darewreck '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.