【问题标题】:how to change a soft keyboard's height at run-time?如何在运行时更改软键盘的高度?
【发布时间】:2019-10-09 18:48:57
【问题描述】:

我正在设计一个软键盘,我想在用户在横向和纵向模式之间进行选择时在运行时更改它的高度。我知道如何在 xml 中更改键的高度,但我需要动态地进行。

我唯一想到的就是从 Keyboard 子类化并覆盖它的 setKeysHeight (int height),但它似乎没用,因为整个键盘停止响应我的点击,并且高度(虽然与以前不同)不在乎上述函数中的“height”。

有什么想法/解决方法吗?

【问题讨论】:

  • 我也在为此苦苦挣扎。调用 setKeysHeight 和 setKeysWidth 似乎没有任何作用.. stackoverflow.com/a/9695482/1241783 的答案似乎部分起作用,但我仍然无法改变键盘高度!
  • 我最终为我需要的每个键盘定义了单独的布局,然后根据需要设置 KeyboardView.setKeyboard(...)。这样,每个需要不同键高的键盘都有一个不同的 Keyboard 对象。
  • 不确定你是否还需要它,但我有点搞定了,现在输入答案
  • 嘿 Jospeh 我想知道您的键盘是否可以正常工作,我目前正在寻找一种解决方案,通过不同的布局更改键盘高度或更改答案中描述的高度,我想要知道我是否可以专门为我的应用程序定义一个键盘视图,或者我是否必须创建一个单独的键盘来实现这一点,如果你能分享一些你是如何做到这一点的知识,那就太好了

标签: android keyboard


【解决方案1】:

原始解决方案发布在https://stackoverflow.com/a/9695482/1241783,但它没有附带解释,所以我在这里扩展一下。

1) 创建一个新类来扩展覆盖 getHeight() 方法的 Keyboard 类。

@Override
public int getHeight() {
   return getKeyHeight() * 3;
}

注意:这里的数字 3 是您的总行数,如果您的键盘有 5 行,则输入 5。

如果你的键盘行高每一行都不一样,这里你需要自己计算并返回总高度(单位是像素,花了我一段时间才弄清楚它不是dp所以需要将dp转换为像素对于所有计算)例如:

@Override
public int getHeight() {
   return row1Height + row2Height + row3Height + row4Height + row5Height;
}

2) 在同一个类中创建一个新的公共函数。

public void changeKeyHeight(double height_modifier)
{
   int height = 0;
   for(Keyboard.Key key : getKeys()) {
      key.height *= height_modifier;
      key.y *= height_modifier;
      height = key.height;
   }
   setKeyHeight(height);
   getNearestKeys(0, 0); //somehow adding this fixed a weird bug where bottom row keys could not be pressed if keyboard height is too tall.. from the Keyboard source code seems like calling this will recalculate some values used in keypress detection calculation
}

如果您不使用 height_modifier 而是设置为特定高度,则需要自己计算 key.y 位置。

如果每行的键盘行高不同,您可能需要检查键,确定它所属的行并将高度设置为正确的值,否则键会相互重叠。还将行高存储在私有变量中,以便在上面的 getHeight() 中使用。 PS:在某些配置下,我在更改键盘高度后无法按下底行键,我发现调用 getNearestKeys() 可以解决这个问题,但我不确定为什么。

注意:key.y是按键的y位置,坐标0从键盘顶部开始,随着数值的增加而下降。例如从键盘顶部坐标 100 点到 100 像素 :)

3) 最后一步是在扩展 InputMethodService 的主类中调用 changeKeyHeight。在 onStartInputView() 内部执行(覆盖它),因为这是在更改高度后(通过首选项或其他方式)重绘键盘的位置。

如果您正在查看 Android 软键盘示例项目,它将是这样的:

@Override public void onStartInputView(EditorInfo attribute, boolean restarting) {
   super.onStartInputView(attribute, restarting);

   // Change the key height here dynamically after getting your value from shared preference or something
   mCurKeyboard.changeKeyHeight(1.5);

   // Apply the selected keyboard to the input view.
   mInputView.setKeyboard(mCurKeyboard);
   mInputView.closing();        

   final InputMethodSubtype subtype = mInputMethodManager.getCurrentInputMethodSubtype();
   mInputView.setSubtypeOnSpaceKey(subtype);
}

干杯!

额外:如果您需要 dp 到像素转换器,代码如下:

private int convertDpToPx(int dp)
{
   return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}

【讨论】:

  • 不再起作用了。调整大小后,底部键停止响应。我检查了 KeyboardView 源,似乎 getNearestKeys 不会触发任何重新计算,因为“if (mGridNeighbors == null)”检查。
【解决方案2】:

我在 Android 6 上使用以下代码:

private void adjustKeyboardKeyHeight (MyKeyboard keyboard, int newKeyHeight) {
   int oldKeyHeight = keyboard.getKeyHeight();
   int verticalGap = keyboard.getVerticalGap();
   int rows = 0;
   for (Keyboard.Key key : keyboard.getKeys()) {
      key.height = newKeyHeight;
      int row = (key.y + verticalGap) / (oldKeyHeight + verticalGap);
      key.y = row * newKeyHeight + (row - 1) * verticalGap;
      rows = Math.max(rows, row + 1);
      }
   keyboard.setHeight(rows * newKeyHeight + (rows - 1) * verticalGap);
}

private static class MyKeyboard extends Keyboard {
   private int height;
   MyKeyboard (Context context, int xmlLayoutResId) {
      super(context, xmlLayoutResId);
      height = super.getHeight();
   }
   @Override public int getKeyHeight() {
      return super.getKeyHeight();
   }
   @Override public int getVerticalGap() {
      return super.getVerticalGap();
   }
   public void setHeight (int newHeight) {
      height = newHeight;
   }
   @Override public int getHeight() {
      return height;
   }
}

【讨论】:

    【解决方案3】:

    布鲁斯的解决方案不再有效。调整大小后,底部键停止响应。看看Keyboard.java:

        public int[] getNearestKeys(int x, int y) {
            if (mGridNeighbors == null) computeNearestNeighbors();
    

    所以 getNearestKeys 不会触发任何计算,computeNearestNeighbors() 不会被多次调用(而且它是私有的,所以你不能直接调用它)。

    我没有改变现有对象的大小,而是修改了 Keyboard.Key 类:

         public class FTKey extends Keyboard.Key {
            FTKey(Resources res, Keyboard.Row parent, int x, int y, XmlResourceParser parser) {
            super(res, parent, x, y, parser);
    
            this.height = (int) (height * FTPref.yScale);
            this.y = this.height * FTPref.yScale; // This works only if all rows of the same height
        }
    

    在 onStartInput() 中,我每次都重新创建所有键盘对象:

    FTPref.yScale = 0.7f;
    mEnglishKeyboard = new FTKeyboard(this ...
    mRussianKeyboard = new FTKeyboard(this ...
    

    仍然需要覆盖 getHeight() 来计算总键盘高度。

    拥有不同高度的键会很棘手,因为您不仅要计算总高度,还要计算每个按钮的 y 位置,它取决于前几行的高度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-21
      • 2015-05-11
      • 1970-01-01
      • 2015-04-18
      相关资源
      最近更新 更多