如何在运行时更改软键盘的高度?

14
我正在设计一个软键盘,希望能够根据用户在横向和纵向模式之间选择的不同来动态更改其高度。我知道如何在xml中更改键的高度,但我需要在运行时实现它。
我想到的唯一方法是从Keyboard类进行子类化,并覆盖其setKeysHeight(int height)方法,但似乎这样做没有用,整个键盘都无法响应我的点击,而且高度(虽然与以前不同)也不关心上述函数中的'height'参数。
有什么想法或解决方法吗?

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

19

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

1)创建一个新类,继承Keyboard类并重写getHeight()方法。

@Override
public int getHeight() {
   return getKeyHeight() * 3;
}
注意:这里的数字3是您的总行数,如果您的键盘有5行,请填写5。
如果您的键盘每行的高度不同,在这里您需要自己计算并返回总高度(单位为像素,花了我一段时间才弄清楚它不是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,而是设置了特定的高度,则需要自己计算关键字的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)”的检查。 - Grrruk

0

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

0
Bruce的解决方案不再起作用了。调整大小后,底部按键停止响应。请查看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位置,并且这取决于前几行的高度。


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