在android中是否有任何方法可以获得设备虚拟键盘的高度

时间:2013-05-28 09:50:01

标签: android sdk

在android中有什么方法可以在运行时获取android设备虚拟键盘的高度。其实我想在键盘上方显示文本框。

12 个答案:

答案 0 :(得分:41)

为了解决这个问题,我编写了一个keyboardHeightProvider,它可以计算浮动软键盘的高度。可以在AndroidManifest.xml中将Activity设置为adjustNone或adjustPan。

https://github.com/siebeprojects/samples-keyboardheight

希比

答案 1 :(得分:35)

我为此尝试了许多建议的方法,但似乎没有一个适用于Android SDL。我认为这要么是因为SDL显示器是"全屏"或者它位于" AbsoluteLayout"因此" View"的高度永远不会改变。这种方法对我有用:

Getting the dimensions of the soft keyboard

mRootWindow = getWindow();
mRootView = mRootWindow.getDecorView().findViewById(android.R.id.content);
mRootView.getViewTreeObserver().addOnGlobalLayoutListener(
    new ViewTreeObserver.OnGlobalLayoutListener() {
    public void onGlobalLayout(){
        Rect r = new Rect();
        View view = mRootWindow.getDecorView();
        view.getWindowVisibleDisplayFrame(r);
        // r.left, r.top, r.right, r.bottom
    }
    });

答案 2 :(得分:29)

是的,您可以在Viewtree Observer和全局布局监听器的帮助下,尝试下面提到的步骤

  1. 获取布局的根视图
  2. 获取此根的Viewtree观察者,并在此基础上添加全局布局侦听器。
  3. 现在无论何时显示软键盘,android都会重新调整屏幕大小,您将收到听众的电话。这就是你现在唯一需要做的就是计算你的根视图在重新调整大小和原始大小之后的高度之间的差异。如果差异超过150则认为这是因为键盘已经膨胀。

    以下是示例代码

    root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener(){
         public void onGlobalLayout(){
               int heightDiff = root.getRootView().getHeight()- root.getHeight();
               // IF height diff is more then 150, consider keyboard as visible.  
            }
      });
    

    此致 Techfist

答案 3 :(得分:6)

将文本框设为父级底部。

android:layout_alignParentBottom="true"

并在清单文件中进行软输入adjustresize

android:windowSoftInputMode="adjustResize"

然后当键盘出现时,文本框将向上移动。

答案 4 :(得分:4)

你无法分辨。不,真的:你根本说不出来。

键盘不需要是任何特定的形状。它不必放在屏幕底部(many选项most popularare not),更改文本字段时不必保持当前大小(几乎没有取决于旗帜)。它甚至不必是rectangular。它也可能只是接管entire screen

(关于类似问题的答案副本Getting the dimensions of the soft keyboard

答案 5 :(得分:3)

即使活动不使用'e'输入模式,我也创建了一个库项目来获取android键盘的高度。

https://github.com/Crysis21/KeyboardHeightProvider

答案 6 :(得分:0)

我的解决方案是以上所有解决方案的组合。这个解决方案也很hacky但解决了问题(至少对我来说)。

  1. 我在屏幕底部有透明背景的临时视图。
  2. 我在清单中的活动代码中添加了android:windowSoftInputMode="adjustResize"标记,如@bill建议。
  3. 现在主要故事在onGlobalLayout()。我计算了临时视图的y轴和根视图的高度之间的差异

    final View view = findViewById(R.id.base);
    
    view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    
        @Override
        public void onGlobalLayout() {
    
            int rootViewHeight = view.getRootView().getHeight();
            View tv = findViewById(R.id.temp_view);
            int location[] = new int[2];
            tv.getLocationOnScreen(location);
            int height = (int) (location[1] + tv.getMeasuredHeight());
            deff = rootViewHeight - height;
            // deff is the height of soft keyboard
    
        }
    });
    
  4. 但是无论如何要解决@ zeeshan0026的问题,清单android:windowSoftInputMode="adjustResize"中只有一个标志就足够了。

答案 7 :(得分:0)

我已经用它在Android中以编程方式获得键盘高度并进行了测试,请尝试一次:

myLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

                @Override
                public void onGlobalLayout() {
                    // TODO Auto-generated method stub
                    Rect r = new Rect();
                    parent.getWindowVisibleDisplayFrame(r);

                    int screenHeight = parent.getRootView().getHeight();
                    int heightDifference = screenHeight - (r.bottom - r.top);
                    Log.d("Keyboard Size", "Size: " + heightDifference);

                    //boolean visible = heightDiff > screenHeight / 3;
                }
            });

谢谢。

答案 8 :(得分:0)

此方法适用于您的活动上的adjustNothing或任何windowSoftInputMode

<activity android:name=".MainActivity"
        android:configChanges="orientation|keyboardHidden|screenSize"
        android:theme="@style/AppTheme"
        android:windowSoftInputMode="stateHidden|adjustNothing"/>

使用PopupWindow,您可以为此使用单独的“键盘行为”,它将通知您键盘的大小。 PopupWindow的高度为屏幕,但宽度为0px,因此您不会看到它,它不会影响您的活动,但会为您提供所需的信息。

创建一个名为KeyboardHeightProvider的类并添加以下代码:

public class KeyboardHeightProvider extends PopupWindow {
    public KeyboardHeightProvider(Context context, WindowManager windowManager, View parentView, KeyboardHeightListener listener) {
        super(context);

        LinearLayout popupView = new LinearLayout(context);
        popupView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        popupView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
            DisplayMetrics metrics = new DisplayMetrics();
            windowManager.getDefaultDisplay().getMetrics(metrics);

            Rect rect = new Rect();
            popupView.getWindowVisibleDisplayFrame(rect);

            int keyboardHeight = metrics.heightPixels - (rect.bottom - rect.top);
            int resourceID = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
            if (resourceID > 0) {
                keyboardHeight -= context.getResources().getDimensionPixelSize(resourceID);
            }
            if (keyboardHeight < 100) {
                keyboardHeight = 0;
            }
            boolean isLandscape = metrics.widthPixels > metrics.heightPixels;
            boolean keyboardOpen = keyboardHeight > 0;
            if (listener != null) {
                listener.onKeyboardHeightChanged(keyboardHeight, keyboardOpen, isLandscape);
            }
        });

        setContentView(popupView);

        setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
        setWidth(0);
        setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
        setBackgroundDrawable(new ColorDrawable(0));

        parentView.post(() -> showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0));
    }

    public interface KeyboardHeightListener {
        void onKeyboardHeightChanged(int keyboardHeight, boolean keyboardOpen, boolean isLandscape);
    }
}

请注意PopupWindow如何具有自己的setSoftInputMode(...),因此无论您将活动设置为什么,PopupWindow仍然会受到键盘打开或关闭的影响,并将提供高度的父活动。 。如果高度为>= 100,则可以假定键盘是打开的。

要使用它,只需在onCreate(...)之后在您的Activity的setContentView(...)方法中实例化它即可:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);

    LinearLayout llRoot = findViewById(R.id.llRoot); //The root layout (Linear, Relative, Contraint, etc...)

    new KeyboardHeightProvider(this, getWindowManager(), llRoot, new KeyboardHeightProvider.KeyboardHeightListener() {
        @Override
        public void onKeyboardHeightChanged(int keyboardHeight, boolean keyboardOpen, boolean isLandscape) {
            Log.i("keyboard listener", "keyboardHeight: " + keyboardHeight + " keyboardOpen: " + keyboardOpen + " isLandscape: " + isLandscape);

            //Do what you want or have to with the parameters..
        }
    });

    //...
}

答案 9 :(得分:0)

我终于找到了提高软/虚拟键盘高度的解决方案。我不能说这在所有设备上都有效,但是我在实际设备和仿真器设备上都尝试过,并且可以工作。我在Android API 16到29的设备上尝试过。有点棘手。这是我的分析。

首先,我尝试通过使用getHeightDifference()之类的功能在屏幕高度和软/虚拟键盘顶部的可见框架高度之间减去。我发现,在第一次创建布局时,就在EditText焦点打开键盘之前,高度差取决于Android系统导航栏,无论导航栏是否显示在设备屏幕内。因此,如果导航栏位于屏幕外部,则heightDifference的值将为0;如果位于屏幕内部,则其值将大于0。我在Integer对象中使用了systemNavigationBarHeight变量(而不是使用原始的int数据)仅通过一次初始化来保存该高度差的第一个值,我假设这是Nav的高度吧。

然后在下一个代码块中,我检查下一个高度差是否大于Android系统中的实际导航栏的高度(或100为默认值,以防万一,如果Android系统中没有导航栏),则我减去再次使用systemNavigationBarHeight的值来获取软/虚拟键盘的实际高度。

希望这对查找其他答案的人有所帮助。

public class MyActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        rootView.getViewTreeObserver()
                .addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
                    private Integer systemNavigationBarHeight = null;
                        
                    @Override
                    public void onGlobalLayout() {
                        int heightDifference = getHeightDifference();
                        if (heightDifference > 0) {
                            if (systemNavigationBarHeight == null) {
                                /* Get layout height when the layout was created at first time */
                                systemNavigationBarHeight = heightDifference;
                            }
                        } else {
                            systemNavigationBarHeight = 0;
                        }

                        if (heightDifference > getDefaultNavigationBarHeight()) {
                            /* Keyboard opened */
                            int keyBoardHeight = heightDifference - systemNavigationBarHeight;
                        } else {
                            /* Keyboard closed */
                        }
                    }
        }
    }
    
    private int getHeightDifference() {
        Point screenSize = new Point();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            getWindowManager().getDefaultDisplay().getRealSize(screenSize);
        } else {
            getWindowManager().getDefaultDisplay().getSize(screenSize);
        }

        Rect rect = new Rect();
        rootView.getWindowVisibleDisplayFrame(rect);
        return screenSize.y - rect.bottom;
    }
    
    private int getDefaultNavigationBarHeight() {
        int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
        if (resourceId > 0) {
            return getResources().getDimensionPixelSize(resourceId);
        }
        return 100;
    }
}

答案 10 :(得分:0)

将导航栏,键盘等添加到窗口后,您可以测量这些插图以检查键盘是否打开。使用Android R,您可以直接测量键盘,但可以依靠先前版本的插图来计算键盘大小。

这适用于棒棒糖及更高版本。

getWindow().getDecorView()
               .setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
             
                   @Override
                   public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
                       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                           mKeyboardShowing =
                                   insets.getInsets(WindowInsets.Type.ime()).bottom > 0;
                           if (mKeyboardShowing) {
                               setKeyboardHeight(
                                       insets.getInsets(WindowInsets.Type.ime()).bottom -
                                       insets.getInsets(WindowInsets.Type.navigationBars()).bottom);
                           }
                       } else {
                           mKeyboardShowing = getNavigationBarHeight() !=
                                              insets.getSystemWindowInsetBottom();
                           if (mKeyboardShowing) {
                               setKeyboardHeight(insets.getSystemWindowInsetBottom() -
                                                 getNavigationBarHeight());
                           }
                       }
                       return v.onApplyWindowInsets(insets);
                   }

                   public int getNavigationBarHeight() {
                       boolean hasMenuKey = ViewConfiguration.get(MainActivity.this)
                                                             .hasPermanentMenuKey();
                       int resourceId = getResources().getIdentifier("navigation_bar_height",
                                                                     "dimen",
                                                                     "android");
                       if (resourceId > 0 && !hasMenuKey) {
                           return getResources().getDimensionPixelSize(resourceId);
                       }
                       return 0;
                   }
               });

答案 11 :(得分:-1)

不要再看了! 我长期以来一直在寻找解决方案。经过几天尝试在SOF上建议的所有技巧后,我找到了真正有效的完美解决方案。

这个GitHub项目以最佳方式演示: https://github.com/siebeprojects/samples-keyboardheight

玩得开心!