GameTextInput 是 Android游戏开发套件 (AGDK) 的一部分。
使用 GameTextInput
库是编写使用软键盘进行文本输入的全屏Android应用程序的更简单的替代方案。
GameTextInput
提供了一个简单的API来显示或隐藏软键盘,设置或获取当前编辑的文本,并在文本更改时接收通知。它并非用于功能齐全的文本编辑器应用程序,但仍然为游戏中典型的用例提供选择和组合区域支持。此外,此库还支持高级 输入法编辑器 (IME) 功能,例如拼写检查、自动完成和多键字符。
在内部,GameTextInput
将输入文本(以及相关状态)累积到内部缓冲区 GameTextInput::currentState_
并通知应用程序其任何更改。然后,应用程序在其注册的回调函数中执行文本处理。
可用性
GameTextInput
可以通过以下方式使用:
与GameActivity一起使用:GameActivity集成了GameTextInput。使用GameActivity的应用程序只能使用集成的GameTextInput。使用说明已在 GameActivity页面 上完整记录。有关GameActivity和GameTextInput集成的示例,请参阅 games-samples存储库。此使用方法不在本指南的范围内。
作为独立库:指南的其余部分描述了使用方法。
请注意,以上两种方法是互斥的。
正式的GameTextInput
版本可在以下渠道获得:
- 在 Google Maven 中的Jetpack游戏库版本
- 在 AGDK下载页面 上的Zip文件版本
本指南涵盖了第一种使用方法。要使用zip文件版本,请参考包内提供的说明。
设置您的构建
GameTextInput
以 Android归档 (AAR) 的形式分发。此AAR包含Java类和C源代码,这些代码实现了GameTextInput
的原生功能。您需要通过 Prefab
将这些源文件包含在您的构建过程中,它将原生库和源代码公开给您的 CMake项目 或 NDK构建。
按照 Jetpack Android游戏 页面上的说明,将
GameTextInput
库依赖项添加到游戏的build.gradle
文件中。请注意,如果您的应用程序正在使用GameActivity,则_不能_使用独立的GameTextInput
库。确保
gradle.properties
包含以下几行:# Tell Android Studio we are using AndroidX. android.useAndroidX=true # Use Prefab 1.1.2 or higher, which contains a fix for "header only" libs. android.prefabVersion=1.1.2 # Required only if you're using Android Studio 4.0 (4.1 is recommended). # android.enablePrefab=true
导入
game-text-input
包并将其添加到项目CMakeLists.txt
文件中的目标中find_package(game-text-input REQUIRED CONFIG) ... target_link_libraries(... game-text-input::game-text-input)
在游戏中一个
.cpp
文件中,添加以下行以包含GameTextInput
实现:#include <game-text-input/gametextinput.cpp>
在使用
GameTextInput
C API的源文件中,包含头文件:#include <game-text-input/gametextinput.h>
编译并运行应用程序。如果您遇到CMake错误,请验证AAR和
build.gradle
文件是否已正确设置。如果找不到#include
文件,请验证您的CMakeLists.txt
配置文件。
集成您的构建
从已附加到JVM的C线程或应用程序主线程中,使用
JNIEnv
指针调用GameTextInput_init
。static GameTextInput* gameTextInput = nullptr; extern "C" JNIEXPORT void JNICALL Java_com_gametextinput_testbed_MainActivity_onCreated(JNIEnv* env, jobject this) { { if(!gameTextInput) gameTextInput = GameTextInput_init(env); ... }
创建一个具有对
InputConnection
访问权限的InputEnabledTextView
Java类。public class InputEnabledTextView extends View implements Listener { public InputConnection mInputConnection; public InputEnabledTextView(Context context, AttributeSet attrs) { super(context, attrs); } public InputEnabledTextView(Context context) { super(context); } public void createInputConnection(int inputType) { EditorInfo editorInfo = new EditorInfo(); editorInfo.inputType = inputType; editorInfo.actionId = IME_ACTION_NONE; editorInfo.imeOptions = IME_FLAG_NO_FULLSCREEN; mInputConnection = new InputConnection(this.getContext(), this, new Settings(editorInfo, true) ).setListener(this); } @Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { if (outAttrs != null) { GameTextInput.copyEditorInfo(mInputConnection.getEditorInfo(), outAttrs); } return mInputConnection; } // Called when the IME input changes. @Override public void stateChanged(State newState, boolean dismissed) { onTextInputEventNative(newState); } @Override public void onImeInsetsChanged(Insets insets) { // handle Inset changes here } private native void onTextInputEventNative(State softKeyboardEvent); }
将创建的
InputEnabledTextView
添加到UI布局。例如,activity_main.xml
中的以下代码可以将其定位在屏幕底部:<com.android.example.gametextinputjava.InputEnabledTextView android:id="@+id/input_enabled_text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" />
将这个新的
InputEnabledTextView
类检索到您的Java活动中。当您使用 View Binding 时,这非常简单。public class MainActivity extends AppCompatActivity { ... private ActivityMainBinding binding; private InputEnabledTextView inputEnabledTextView; private native void setInputConnectionNative(InputConnection c); @Override protected void onCreate(Bundle savedInstanceState) { ... binding = ActivityMainBinding.inflate(getLayoutInflater()); inputEnabledTextView = binding.inputEnabledTextView; inputEnabledTextView.createInputConnection(InputType.TYPE_CLASS_TEXT); setInputConnectionNative(inputEnabledTextView.mInputConnection); }
在您的C库中,将
inputConnection
传递到GameTextInput_setInputConnection
。在GameTextInput_setEventCallback
中传递一个回调函数,以便在状态更改时作为C状态结构GameTextInputState
接收事件通知。extern "C"JNIEXPORT void JNICALL Java_com_gametextinput_testbed_MainActivity_setInputConnectionNative( JNIEnv *env, jobject this, jobject inputConnection) { GameTextInput_setInputConnection(gameTextInput, inputConnection); GameTextInput_setEventCallback(gameTextInput,[](void *ctx, const GameTexgtInputState *state) { if (!env || !state) return; // process the newly arrived text input from user. __android_log_print(ANDROID_LOG_INFO, "TheGreateGameTextInput", state->text_UTF8); }, env); }
在您的C库中,调用
GameTextInput_processEvent
,它会在内部调用您在上一步中注册的回调函数,以便您的应用程序在状态更改时处理事件。extern "C" JNIEXPORT void JNICALL Java_com_gametextinput_testbed_InputEnabledTextView_onTextInputEventNative( JNIEnv* env, jobject this, jobject soft_keyboard_event) { GameTextInput_processEvent(gameTextInput, soft_keyboard_event); }
实用程序函数
GameTextInput
库包含实用程序函数,允许您在Java状态对象和C状态结构之间进行转换。通过 GameTextInput_showIme
和 GameTextInput_hideIme
函数访问显示和隐藏IME的功能。
参考资料
在使用GameTextInput
创建应用程序时,开发人员可能会发现以下内容很有用:
反馈
关于 GameTextInput
的任何问题,请在 Google IssueTracker 上提交 Bug。