【问题标题】:How do libgdx detect keyboard presencelibgdx 如何检测键盘的存在
【发布时间】:2012-03-07 16:04:59
【问题描述】:

在文本域中书写时,我需要将文本域向上移动,以便在键盘弹出时让文本域可见。

libgdx 是否有某种方法可以在键盘可见时返回 true,在键盘关闭时返回 false?

【问题讨论】:

  • 这与libgdx无关,你想监听一个原生的Android事件。这个问题已经被问及回答了
  • 有点,但如果它不是由 LibGDX 提供的,那么监听这个事件的实现工作就会大得多;)。

标签: android libgdx


【解决方案1】:

以下代码将检测您何时按下文本字段,阻止它显示键盘,然后打开一个随键盘上下移动的本机对话框。它将从本机对话框中获取输入,最后将其放回您的文本字段中:

    textField.setOnscreenKeyboard(new TextField.OnscreenKeyboard() {
        @Override
        public void show(boolean visible) {
            //Gdx.input.setOnscreenKeyboardVisible(true);
            Gdx.input.getTextInput(new Input.TextInputListener() {
                @Override
                public void input(String text) {
                    textField.setText(text);
                }

                @Override
                public void canceled() {
                    System.out.println("Cancelled.");
                }
            }, "Title", "Default text...");
        }
    });

祝你好运!

【讨论】:

  • 知道我们如何改变这个原生对话框的样式吗?
  • 没有。我猜你不能这样做,因为它会在 Android 和 iPhone 以及 Java 桌面等之间有所不同。简而言之:它的原生 => 它的原生工作!
【解决方案2】:

我知道我正在回答一个旧线程,但我正在谷歌上搜索这个问题的答案,但在任何地方都找不到。现在我自己创建了一个解决方案。以下是如何以优雅的方式在 Android 上执行此操作:) 我正在创建一个 ApplicationBundle 来捆绑接口以添加特定于平台的东西。如果您想使用 RoboVM,您也可以在 iOS 上执行此操作。

我的解决方案:

在核心项目中创建一个 SizeChangeListener 接口:

public interface SizeChangeListener {
    public void onSizeChange(float width, float height);
}

在核心项目中创建一个View界面:

public interface View {
    public void onSizeChange(float width, float height);
    public void addListener(SizeChangeListener sizeChangeListener);
    public float getWidth();
    public float getHeight();
}

创建一个实现 View 接口的 AndroidView:

public class AndroidView implements View {

    private ArrayList<SizeChangeListener> listeners = new ArrayList<SizeChangeListener>();
    private float width, height;
    public AndroidView(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public void addListener(SizeChangeListener listener) {
        listeners.add(listener);
    }

    public void onSizeChange(float width, float height) {
        this.width = width;
        this.height = height;
        for(SizeChangeListener listener : listeners)
            listener.onSizeChange(width, height);
    }

    public float getWidth() {
        return width;
    }

    public float getHeight() {
        return height;
    }

}

在核心项目中创建一个ApplicationBundle

public class ApplicationBundle {

    private final View view;

    public ApplicationBundle(View view) {
        this.view = view;
    }

    public View getView() {
        return view;
    }
}

从核心项目进行必要的导入。在 Android 项目的 AndroidLauncher 中添加以下内容:

public class AndroidLauncher extends AndroidApplication {

    private View rootView;
    private AndroidView androidView;
    private int width, height;

    @Override
    protected void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
        rootView = this.getWindow().getDecorView().getRootView();
        Rect rect = new Rect();
        rootView.getWindowVisibleDisplayFrame(rect);
        width = rect.width();
        height = rect.height();
        androidView = new AndroidView(width, height);

        rootView.addOnLayoutChangeListener(new OnLayoutChangeListener() {

            @Override
            public void onLayoutChange(View v, int left, int top, int right,
                    int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {

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

                if(!(width == rect.width() && height == rect.height())) {
                    width = rect.width();
                    height = rect.height();
                    androidView.onSizeChange(width, height);
                }
            }

        }); 

        initialize(new DigMeApp(new ApplicationBundle(androidView)), config);
    }
}

在核心项目的主 MyApp 中的 create() 方法中,将 SizeChangeListener 实现添加到您从构造函数获得的视图中。

public class MyApp extends Game { // or ApplicationAdapter
    private View view;
    private Stage stage;
    // your own variables

    public MyApp(ApplicationBundle applicationBundle) {
        view = applicationBundle.getView();
    }

    @Override
    public void create () {
        stage = new Stage();
        // add some textfields
    final TextField tf1 = new TextField("", skin);
    final TextField tf2 = new TextField("", skin);

    tf1.setWidth((float)view.getWidth() * 0.6f);
    tf2.setWidth((float)view.getWidth() * 0.6f);
    tf1.setHeight((float)view.getHeight() * 0.05f);
    tf2.setHeight((float)view.getHeight() * 0.05f);
        view.addListener(new SizeChangeListener() {         
            @Override
            public void onSizeChange(float width, float height) {
                Gdx.app.log("INFO", "Visible area: " + width + "   " + height);
                Gdx.app.log("INFO", "Stage area: " + stage.getWidth() + "   " + stage.getHeight());
                float keyboardHeight = getKeyboardHeight();

// MOVE THEM OUT OF THE WAY :)

                tf1.addAction(Actions.moveTo(width / 2 - tf1.getWidth() / 2.0f, keyboardHeight + (6 * (height / 8)), 1, Interpolation.sineOut));
                tf2.addAction(Actions.moveTo(width / 2 - tf2.getWidth() / 2.0f, keyboardHeight + (7 * (height / 8)), 1, Interpolation.sineOut));


//              Gdx.gl20.
//              tf.setPosition(width / 2 - (tf.getWidth() / 2.0f), 0);
            }
        });
}

也许像我一样创建一个小的键盘高度方法:

private float getKeyboardHeight() {
        return stage.getHeight() - view.getHeight();
    }

【讨论】:

  • 我喜欢这个答案,它在我测试过的所有设备上都运行良好。我唯一的评论是view.getHeight() 如果您强制 libgdx 为特定分辨率,则需要缩放以匹配舞台或相机尺寸。 @Willempie 你有适用于 iOS 的解决方案吗?
  • 这是一个很好的答案,效果很好,谢天谢地,我不必实现 iOS 方式,所以这不是问题。这应该是选定的答案,尽管我有一个警告。当我触摸文本字段时,当键盘出现时,我的应用程序顶部的黑色横幅也会出现,其中包含我的应用程序名称。似乎是rootView = this.getWindow().getDecorView().getRootView(); 知道如何避免这种情况?
  • [已解决] this.requestWindowFeature(Window.FEATURE_NO_TITLE); 我在设置 rootView 之前添加了这一行
  • 即使我打算在我的游戏中使用这种方法,大约 10/20 次中有 1 次,新的尺寸没有被检测到,我也不知道为什么。无法复制,看起来几乎是随机的:(
  • 很好的解决方案,可惜需要Min API Level 11
【解决方案3】:

试试

Gdx.input.isPeripheralAvailable(Input.Peripheral.OnscreenKeyboard);

我只是在文档中查看了这个,不知道它是否真的有效。但是

Gdx.input.setOnscreenKeyboardVisible(boolean visible);

方法也可以使用(像这样你定义键盘何时可见,何时不可见)。

【讨论】:

  • 试过Input.Peripheral.OnscreenKeyboard,但在android上运行应用时总是如此。但我会尝试手动完成,谢谢你的提示:)
  • 否则,正如 Andrei Bodnarescu 所建议的,您始终可以按照stackoverflow.com/questions/4745988/… 中的描述来监听事件,使用与stackoverflow.com/questions/9584959/… 中描述的相同的结构。干杯!
  • 它似乎总是返回 true no?
猜你喜欢
  • 2023-03-06
  • 1970-01-01
  • 2020-03-30
  • 2012-09-10
  • 2011-02-23
  • 2013-04-07
  • 2018-07-21
  • 2015-02-16
相关资源
最近更新 更多