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

5

我正在为三星Galaxy Tab 3开发一个PhoneGap应用程序。当这个应用程序处于全屏模式时,软键盘会隐藏文本输入字段,无法滚动页面查看内容。我该如何解决这个问题?


我在其中没有看到问题... - George Mitchell
乔治,你是对的。我刚刚添加了这个问题。我必须等待8小时才能添加自己的答案。 - Jorge Marmolejo
2个回答

17

在浏览了这个网站上几乎所有的可能解决方案之后,仍然没有任何效果。最终我找到了两种解决方法:

https://dev59.com/XGs05IYBdhLWcg3wJurp#19494006

此链接展示了一个用于解决安卓应用程序问题的解决方法;然而我没有任何在安卓上工作的经验,因此问题是:如何将此代码段包含在 Phonegap 项目中?

https://dev59.com/NHbZa4cB1Zd3GeqPFm6q#18610405

此链接提供了针对 Phonegap 的解决方法,但对我没有起作用,更重要的是,它给了我一个关于如何在 Phonegap 项目中添加自定义安卓代码的想法。

解决方法

1- 在您的 Phonegap 项目中创建以下类(如第一个链接中所示):



    package com.test.android;

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

    public class AndroidBug5497Workaround {
        // 更多信息请参见 https://code.google.com/p/android/issues/detail?id=5497
        // 要使用此类,请在已设置其内容视图的Activity上调用assistActivity()。

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

        private View mChildOfContent; // Activity的根视图
        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)) {
                    // 键盘可能刚刚变为可见状态
                    frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
                } else {
                    // 键盘可能刚刚变为隐藏状态
                    frameLayoutParams.height = usableHeightSansKeyboard;
                }
                mChildOfContent.requestLayout(); // 重新绘制视图
                usableHeightPrevious = usableHeightNow;
            }
        }

        private int computeUsableHeight() {
            Rect r = new Rect();
            mChildOfContent.getWindowVisibleDisplayFrame(r); // 计算Activity的可用高度
            return (r.bottom - r.top);
        }

}

这个类可以放在项目的这个位置:(我无法在该论坛中加载图像,需要至少10个声望)。请在此 url 中查找图像示例:

更清晰的检查

2- 每当您创建一个 phonegap 项目时,都会获得一个名为 your_project_name.java 的类。在我的情况下,它是 test1.java。编辑该类并在 onCreate 方法中添加以下语句:


    AndroidBug5497Workaround.assistActivity(this);

您的代码应如下所示:


    public class test1 extends DroidGap
    {
        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            // Set by  in config.xml
            super.loadUrl(Config.getStartUrl());
            //super.loadUrl("file:///android_asset/www/index.html")
            AndroidBug5497Workaround.assistActivity(this);
        }
    }
     

3- 这解决了我的应用程序问题。


谢谢,适用于Galaxy S3的Cordova 3应用程序。 - Mithun Sreedharan
1
可以确认这段代码在我使用的运行着4.4.4的OnePlus手机上仍然有效,两年过去了 - 非常感谢! - Someguy123
我本应该在 Cordova 6.0.0 中使用这个修复方法,它仍然像魔法一样有效。Cordova 会修复它吗?还是我错过了什么? - Matt

3

我采用了Jorge的方案,这对我非常有效!但屏幕的大小调整得有些笨重,我希望它能够更平滑地调整大小。因此我查找了如何对视图进行动画处理,发现了这个

将两者结合起来的代码如下:

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

public class AdjustInputHeight {

    // 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 void assistActivity (Activity activity) {
        new AdjustInputHeight(activity);
    }

    private View mChildOfContent;
    private int usableHeightPrevious;
    private ValueAnimator animateCollapseView = null;
    private ValueAnimator animateExpandView = null;
    private boolean keyboardIsUp = false;
    DecelerateInterpolator sDecelerator = new DecelerateInterpolator();
    private FrameLayout.LayoutParams frameLayoutParams;

    private AdjustInputHeight(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;

            //check if the view got smaller (because keyboard is shown) and is not already up.
            if (heightDifference > (usableHeightSansKeyboard/4) && (!this.keyboardIsUp)) {

                // we need to create the collapse animator the only the first time we rise the keyboard
                if (this.animateCollapseView == null) {
                    this.animateCollapseView = ValueAnimator.ofInt(usableHeightSansKeyboard, (usableHeightSansKeyboard-heightDifference));
                    this.animateCollapseView.setDuration(500);
                    this.animateCollapseView.setInterpolator(sDecelerator);
                    this.animateCollapseView.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                        public void onAnimationUpdate(ValueAnimator animation) {
                            Integer value = (Integer) animation.getAnimatedValue();
                            frameLayoutParams.height = value.intValue();
                            mChildOfContent.requestLayout();
                        }
                    });
                }

                this.animateCollapseView.start();
                // keyboard probably just became visible        
                this.keyboardIsUp = true;

            //lower the keyboard only if it is up.  
            } else if (this.keyboardIsUp) {

                // we need to create the expand animator the only the first time we lower the keyboard
                if (this.animateExpandView == null) {   
                    this.animateExpandView = ValueAnimator.ofInt((usableHeightSansKeyboard-heightDifference), usableHeightSansKeyboard);
                    this.animateExpandView.setDuration(200);
                    this.animateExpandView.setInterpolator(sDecelerator);
                    this.animateExpandView.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                        public void onAnimationUpdate(ValueAnimator animation) {
                            Integer value = (Integer) animation.getAnimatedValue();
                            frameLayoutParams.height = value.intValue();
                            mChildOfContent.requestLayout();
                        }
                    });
                }

                this.animateExpandView.start();
                // keyboard probably just became hidden
                this.keyboardIsUp = false;
            }

            usableHeightPrevious = usableHeightNow;
        }
    }

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

当然,您可以根据自己的需求更改动画持续时间和插值器。


好主意,但如果您必须在同一视图中输入文本,则无法正常工作。 - AndroidRuntimeException

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接