Согласно документации , View
(редактор) получает команды от клавиатуры (IME) через InputConnection
и отправляет команды на клавиатуру через InputMethodManager
.
![enter image description here](https://i.stack.imgur.com/tRMN1.png)
Я покажу весь код ниже, но вот шаги.
1.Сделайте так, чтобы клавиатура отображалась
Поскольку представление отправляет команду на клавиатуру, ему необходимо использовать InputMethodManager
.В качестве примера мы скажем, что при касании вида он покажет клавиатуру (или скроет ее, если он уже отображается).
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_IMPLICIT_ONLY);
}
return true;
}
Вид также должен иметь setFocusableInTouchMode(true)
установить ранее.
2.Получать ввод с клавиатуры
Чтобы представление получало ввод с клавиатуры, необходимо переопределить onCreateInputConnection()
.Это возвращает InputConnection
, который клавиатура использует для связи с представлением.
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
outAttrs.inputType = InputType.TYPE_CLASS_TEXT;
return new MyInputConnection(this, true);
}
outAttrs
указывает, какую клавиатуру запрашивает представление.Здесь мы просто запрашиваем нормальную текстовую клавиатуру.Выбор TYPE_CLASS_NUMBER
приведет к отображению цифровой клавиатуры (если доступно).Есть много других вариантов.См. EditorInfo
.
Вы должны вернуть InputConnection
, который обычно является пользовательским подклассом BaseInputConnection
.В этом подклассе вы предоставляете ссылку на вашу редактируемую строку, которую клавиатура будет обновлять.Поскольку SpannableStringBuilder
реализует интерфейс Editable
, мы будем использовать его в нашем базовом примере.
public class MyInputConnection extends BaseInputConnection {
private SpannableStringBuilder mEditable;
MyInputConnection(View targetView, boolean fullEditor) {
super(targetView, fullEditor);
MyCustomView customView = (MyCustomView) targetView;
mEditable = customView.mText;
}
@Override
public Editable getEditable() {
return mEditable;
}
}
Все, что мы здесь сделали, - это предоставили вводсоединение со ссылкой на текстовую переменную в нашем пользовательском представлении.BaseInputConnection
позаботится о редактировании этого mText
.Это вполне может быть все, что вам нужно сделать.Однако вы можете проверить исходный код и посмотреть, какие методы говорят «реализация по умолчанию», особенно «реализация по умолчанию ничего не делает».Это другие методы, которые вы можете переопределить в зависимости от степени вовлеченности вашего представления редактора.Вам также следует просмотреть все имена методов в документации .Ряд из них имеют заметки для «редакторов».Обратите на это особое внимание.
Некоторые клавиатуры по какой-то причине не посылают определенный ввод через InputConnection
(например, удаление , ввод и некоторые клавиши цифровой клавиатуры ).Для тех, кого я добавил OnKeyListener
.Протестировав эту настройку на пяти разных программных клавиатурах, казалось, все работает.Дополнительные ответы, относящиеся к этому, приведены здесь:
Полный код проекта
Вот мой полный пример для справки.
![enter image description here](https://i.stack.imgur.com/Tg644.png)
MyCustomView.java
public class MyCustomView extends View {
SpannableStringBuilder mText;
public MyCustomView(Context context) {
this(context, null, 0);
}
public MyCustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyCustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setFocusableInTouchMode(true);
mText = new SpannableStringBuilder();
// handle key presses not handled by the InputConnection
setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (event.getUnicodeChar() == 0) { // control character
if (keyCode == KeyEvent.KEYCODE_DEL) {
mText.delete(mText.length() - 1, mText.length());
Log.i("TAG", "text: " + mText + " (keycode)");
return true;
}
// TODO handle any other control keys here
} else { // text character
mText.append((char)event.getUnicodeChar());
Log.i("TAG", "text: " + mText + " (keycode)");
return true;
}
}
return false;
}
});
}
// toggle whether the keyboard is showing when the view is clicked
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_IMPLICIT_ONLY);
}
return true;
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
outAttrs.inputType = InputType.TYPE_CLASS_TEXT;
// outAttrs.inputType = InputType.TYPE_CLASS_NUMBER; // alternate (show number pad rather than text)
return new MyInputConnection(this, true);
}
}
MyInputConnection.java
public class MyInputConnection extends BaseInputConnection {
private SpannableStringBuilder mEditable;
MyInputConnection(View targetView, boolean fullEditor) {
super(targetView, fullEditor);
MyCustomView customView = (MyCustomView) targetView;
mEditable = customView.mText;
}
@Override
public Editable getEditable() {
return mEditable;
}
// just adding this to show that text is being committed.
@Override
public boolean commitText(CharSequence text, int newCursorPosition) {
boolean returnValue = super.commitText(text, newCursorPosition);
Log.i("TAG", "text: " + mEditable);
return returnValue;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.editorview.MainActivity">
<com.example.editorview.MyCustomView
android:id="@+id/myCustomView"
android:background="@android:color/holo_blue_bright"
android:layout_margin="50dp"
android:layout_width="300dp"
android:layout_height="150dp"
android:layout_centerHorizontal="true"
/>
</RelativeLayout>
В коде MainActivity.java нет ничего особенного.
Пожалуйста, оставьте комментарий, если это не работает длявы.Я использую это базовое решение для пользовательского EditText в библиотеке, которую я создаю, и если есть какие-либо крайние случаи, в которых это не работает, я хочу знать.Если вы хотите просмотреть этот проект, пользовательское представление будет здесь .Это InputConnection
здесь здесь .
Связанные