【问题标题】:Enter key handling in Libgdx TextField在 Libgdx TextField 中输入密钥处理
【发布时间】:2014-02-17 17:11:09
【问题描述】:

我在我的 libgdx 应用程序中设置了一个包含三个 TextField 的舞台,我在桌面模式和 Android 模式下得到了不同的行为。在 Android 上,输入回车键会将光标移动到下一个 TextField。在桌面上,输入回车键没有任何作用。

如何使光标在两个平台上一致移动?我希望能够在用户输入时将焦点设置到另一个字段。在 Android 上,无论我将焦点设置到什么位置,默认的输入键行为都会在此之后将焦点跳转到该字段。

这是我目前用来移动光标并清除下一个字段的代码:

    stage.addListener(new InputListener() {
        @Override
        public boolean keyUp(InputEvent event, int keycode) {
            if (keycode == Input.Keys.ENTER) {
                nextField();
            }
            return false;
        }
    });
    Gdx.input.setInputProcessor(stage);
}

private void nextField() {
    TextField nextField = 
            stage.getKeyboardFocus() == text1
            ? text2
            : stage.getKeyboardFocus() == text2
            ? text3
            : text1;
    nextField.setText("");
    stage.setKeyboardFocus(nextField);
}

我已尝试取消事件或从处理程序方法返回 true,但在我的代码完成后焦点仍在移动。

我的完整示例代码是on GitHub

【问题讨论】:

    标签: java android input libgdx


    【解决方案1】:

    TextField 使用一个私有的内部 InputListener,它在构造函数中被初始化并且不能轻易被覆盖。改变焦点的相关代码在这个监听器的keyTyped方法期间:

    public boolean keyTyped (InputEvent event, char character) {
         [...]
         if ((character == TAB || character == ENTER_ANDROID) && focusTraversal)
             next(Gdx.input.isKeyPressed(Keys.SHIFT_LEFT) || Gdx.input.isKeyPressed(Keys.SHIFT_RIGHT));
         [...]
    }
    

    一个简单的解决方案是一起禁用焦点遍历并设置一个自动执行遍历的 com.badlogic.gdx.scenes.scene2d.ui.TextFieldListener:

    TextField textField
    textField.setFocusTraversal(false);
    textField.setTextFieldListener(new TextFieldListener() {
        @Override
        public void keyTyped(TextField textField, char key) {
            if ((key == '\r' || key == '\n')){
                textField.next(Gdx.input.isKeyPressed(Keys.SHIFT_LEFT) || Gdx.input.isKeyPressed(Keys.SHIFT_RIGHT));
            }
        }
    });
    

    如果您需要能够使用 TextFields setFocusTraversal 方法启用和禁用焦点遍历,那么在将内部 InputListener 添加到 TextField 时将其包装在您自己的侦听器中也会有一个非常hacky的解决方案(但我会 推荐这个):

    class MyTextField extends TextField{
    
    class InputWrapper extends InputListener{
        private final InputListener l;
    
        public InputWrapper(InputListener l) {
            super();
            this.l = l;
        }
    
        @Override
        public boolean handle(Event e) {
            return l.handle(e);
        }
    
        @Override
        public boolean touchDown(InputEvent event, float x, float y,
                int pointer, int button) {
            return l.touchDown(event, x, y, pointer, button);
        }
    
        @Override
        public void touchUp(InputEvent event, float x, float y,
                int pointer, int button) {
            l.touchUp(event, x, y, pointer, button);
        }
    
        @Override
        public void touchDragged(InputEvent event, float x, float y,
                int pointer) {
            l.touchDragged(event, x, y, pointer);
        }
    
        @Override
        public boolean mouseMoved(InputEvent event, float x, float y) {
            return l.mouseMoved(event, x, y);
        }
    
        @Override
        public void enter(InputEvent event, float x, float y, int pointer,
                Actor fromActor) {
            l.enter(event, x, y, pointer, fromActor);
        }
    
        @Override
        public void exit(InputEvent event, float x, float y, int pointer,
                Actor toActor) {
            l.exit(event, x, y, pointer, toActor);
        }
    
        @Override
        public boolean scrolled(InputEvent event, float x, float y,
                int amount) {
            return l.scrolled(event, x, y, amount);
        }
    
        @Override
        public boolean keyDown(InputEvent event, int keycode) {
            return l.keyDown(event, keycode);
        }
    
        @Override
        public boolean keyUp(InputEvent event, int keycode) {
            return l.keyUp(event, keycode);
        }
        @Override
        public boolean keyTyped(InputEvent event, char character) {
            if (isDisabled()) {
                return false;
            } else if ((character == '\r' || character == '\n')){
                next(Gdx.input.isKeyPressed(Keys.SHIFT_LEFT) || Gdx.input.isKeyPressed(Keys.SHIFT_RIGHT));
                return true;
            }
            return l.keyTyped(event, character);
        }
    
    }
    
    public MyTextField(String text, Skin skin, String styleName) {
        super(text, skin, styleName);
    }
    
    public MyTextField(String text, Skin skin) {
        super(text, skin);
    }
    
    public MyTextField(String text, TextFieldStyle style) {
        super(text, style);
    }
    
    boolean initialized = false;
    @Override
    public boolean addListener (EventListener l) {
        if (!initialized) {
            if (!(l instanceof InputListener)) {
                throw new IllegalStateException();
            }
            initialized = true;
            return super.addListener(new InputWrapper((InputListener) l));
        }
        return super.addListener(l);
    }
    }
    

    编辑: 再想一想,您也可以通过简单地覆盖 TextField 的 setFocusTraversal 并在调用此方法期间启用/禁用您自己的侦听器来使用第一个解决方案。

    【讨论】:

    • 我认为禁用焦点遍历将完全符合我的需要。谢谢。
    • 它成功了,我已经更新了我的sample code 以包含它。赏金是你的。
    【解决方案2】:

    我找到了一种解决方法,但我仍然希望有一个更简洁的解决方案,让两个平台的行为方式相同。

    我添加了一个标志来指示默认情况下焦点是否会移动,如果焦点不会自行移动,我只会更改焦点。然后,我从 Android 的 MainActivity 类或桌面的 Main 类设置该标志。我已经发布了完整的示例代码on GitHub

    private void nextField() {
        TextField nextField = 
                stage.getKeyboardFocus() == text1
                ? text2
                : stage.getKeyboardFocus() == text2
                ? text3
                : text1;
        nextField.setText("");
        if ( ! isFocusMovedAutomatically) {
            stage.setKeyboardFocus(nextField);
        }
    }
    

    【讨论】:

      【解决方案3】:

      gdx-1.9.4 中,我能够做到以下几点:

      final TextField newMessageTextField = new TextField("", uiSkin){
          @Override
          protected InputListener createInputListener () {
              return new TextFieldClickListener(){
                  @Override
                  public boolean keyUp(com.badlogic.gdx.scenes.scene2d.InputEvent event, int keycode) {
                      System.out.println("event="+event+" key="+keycode);
                      return super.keyUp(event, keycode);
                  };
              };
          }
      };
      

      按下箭头并聚焦在我拥有的 TextField 上

      event=keyUp key=19
      event=keyUp key=20
      event=keyUp key=22
      event=keyUp key=21
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-09-03
        • 1970-01-01
        • 2019-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多