Как я могу использовать пользовательский шрифт во входной области метода ввода?
Мы разрабатываем приложение, в котором нам нужно использовать собственный шрифт (a Typeface
, загруженный из активов приложения) в EditText
. Android-метод ввода сообщает следующее:
Когда фокус ввода перемещается в редактируемое текстовое поле или выходит из него, Android показывает или скрывает метод ввода (например, экранную клавиатуру), если это необходимо. Система также принимает решения о том, как ваш пользовательский интерфейс и текстовое поле появляются над методом ввода. Например, , когда вертикальное пространство на экране ограничено, текстовое поле может заполнить все пространство над методом ввода.
Это смелая часть, которая нас подводит. Фраза "текстовое поле может заполнить...", похоже, вводит в заблуждение, поскольку используемое текстовое поле не является EditText
, которое мы настраиваем с помощью нашего пользовательского шрифта. ( ПРИМЕЧАНИЕ: ответы до сих пор объясняют, как установить пользовательский шрифт в EditText
. Мы уже настраиваем пользовательский шрифт в EditText
.. Пожалуйста, прочитайте вопрос тщательно перед ответом.) Здесь скриншот со скрытым способом ввода:
![the dialog]()
Здесь, что происходит, когда отображается мягкая клавиатура, и вертикальное пространство ограничено:
![constrained vertical space]()
Как вы можете видеть, шрифт в текстовом поле над методом ввода не является нашим пользовательским шрифтом (я предполагаю, что это шрифт Roboto по умолчанию). Это происходит для каждой мягкой клавиатуры, которую мы пробовали в качестве метода ввода.
Я хочу подчеркнуть, что когда пространство ограничено, этот вид над клавиатурой генерируется внутри системы, а не каким-либо из нашего кода.
Основной вопрос: есть ли способ (и, если да, что это такое?), чтобы контролировать внешний вид этого (из-за отсутствия лучшей терминологии) прокси-представления — как минимум, чтобы заставить его использовать наш собственный шрифт
Это был бы дополнительный бонус, если мы могли бы также контролировать макет и внешний вид всей области прокси над клавиатурой (включая кнопку "Готово" ). Мы используем вариацию метода, описанного в этой теме, чтобы наша деятельность использовала локаль, отличную от той, которая установлена в системе, но локаль действия явно не является здесь применяется. (Если бы это было так, кнопка была бы слева и читала бы "בוצע", как это происходит, если я изменю языковой стандарт устройства на иврит. [EDIT: Я могу получить правильную метку кнопки, используя атрибут android:imeActionLabel
на EditText
. Однако я не знаю, как контролировать направленность макета.])
РЕДАКТИРОВАТЬ По запросу, здесь, как я создаю свой диалог (соответствующие фрагменты, взятые из DialogFragment
):
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Dialog dlg = new Dialog(getActivity(), android.R.style.Theme_Holo_Light_Dialog_NoActionBar);
dlg.setContentView(R.layout.edit_note_dialog);
mAnimator = (ViewAnimator) dlg.findViewById(R.id.animator);
final Typeface hebrew = SystemData.getHebrewFont();
mNoteEditor = (EditText) dlg.findViewById(R.id.note_field);
mNoteEditor.setTypeface(hebrew);
// etc. (setting fonts for other elements, adding listeners, etc.)
}
А вот макет:
<?xml version="1.0" encoding="utf-8"?>
<ViewAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/animator"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="10dp"
android:text="@string/loading" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:background="@android:color/black"
android:gravity="center"
android:text="@string/edit_note_title"
android:textColor="@android:color/white"
android:textSize="20sp" />
<TextView
android:id="@+id/citation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/title"
android:layout_centerHorizontal="true"
android:background="@android:color/black"
android:gravity="center"
android:textColor="@android:color/white"
android:textSize="16sp" />
<LinearLayout
android:id="@+id/actions"
style="?android:attr/buttonBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_margin="5dp" >
<Button
android:id="@+id/cancel"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:gravity="center"
android:minWidth="32dp"
android:text="@string/cancel"
android:textSize="@dimen/nav_interior_item_size" />
<Button
android:id="@+id/close"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:gravity="center"
android:minWidth="32dp"
android:text="@string/save"
android:textSize="@dimen/nav_interior_item_size" />
</LinearLayout>
<Button
android:id="@+id/undo"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_margin="5dp"
android:text="@string/edit_note_undo"
android:textSize="@dimen/nav_interior_item_size" />
<Button
android:id="@+id/redo"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_margin="5dp"
android:text="@string/edit_note_redo"
android:textSize="@dimen/nav_interior_item_size" />
<EditText
android:id="@+id/note_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/actions"
android:layout_below="@+id/citation"
android:focusableInTouchMode="true"
android:gravity="top"
android:hint="@string/edit_note_hint"
android:imeActionLabel="@string/done"
android:inputType="textMultiLine|textNoSuggestions"
android:lineSpacingMultiplier="1.2" />
</RelativeLayout>
</ViewAnimator>
Ответы
Ответ 1
Было бы просто, если бы у вас был экземпляр InputMethodService.
Существует способ установить theme или даже установить извлеченный вид.
Проблема заключается в том, что вам нужно создать пользовательскую реализацию Input Method, и пользователям придется выбирать ее в системных настройках.
Update:
Вы можете попробовать:
-
-
android:windowSoftInputMode="adjustResize"
- сделать прокручиваемое представление
или
-
- используйте IME_FLAG_NO_EXTRACT_UI
- установите
OnEditorActionListener
на EditText
, чтобы на клавиатуре появилась кнопка действия.
- создавать пользовательские макеты или скрывать/показывать элементы, когда высота экрана слишком мала. Например, скрыть кнопки внизу и показать кнопки с правой стороны. Он может выглядеть так же, как в режиме просмотра экстракта по умолчанию.
макетщик для диалога или EditText:
mViewContainer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//unregister the layout listener if needed.
int heightPixels = mViewContainer.getHeight();
Resources resources = mContext.getResources();
int heightDip = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, heightPixels, resources.getDisplayMetrics());
if (heightDip < MIN_HEIGHT) {
mBottomButtons.setVisibility(View.GONE);
mSideButtons.setVisibility(View.VISIBLE);
} else {
mBottomButtons.setVisibility(View.VISIBLE);
mSideButtons.setVisibility(View.GONE);
}
}
});
Изменение видимости на GONE запросит ретрансляцию, и слушатель снова запустится, что может привести к циклу.
Ответ 2
Единственный способ, которым я могу видеть, - отключить полноэкранный режим редактирования для вашего EditText, который автоматически срабатывает, когда ваш EditText недостаточно высок.
mNoteEditor.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
Вы можете исправить проблемы изменения размера диалогового окна с помощью
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
Возможно, ваш диалог должен быть заключен в ScrollView
.
Ответ 3
Я думаю, что, как утверждают другие, это, к сожалению, выше IME и может быть невозможно через поддерживаемые API.
Остерегайтесь взломанного и непроверенного решения:
Копаясь в исходном коде Android, я обнаружил, что каждый IME содержит реализацию AbstractInputMethodService
. Android обеспечивает стандартную реализацию (android.inputmethodservice.InputMethodService
), которая, если вы посмотрите, имеет общедоступный метод setExtractView
и метод onCreateExtractTextView
, который надувает com.android.internal.R.layout.input_method_extract_view.xml
, который, в свою очередь, содержит com.android.internal.R.id.inputExtractEditText
! Таким образом, хакерское решение будет состоять в том, чтобы надеяться, что для большинства ваших IME-интерфейсов InputMethodServices вашего клиента этот же XML (который, насколько я могу судить, был в Android некоторое время), и вы можете попытаться получить ссылку на этот EditText на его ID и изменить его шрифт. К сожалению, я не уверен, что в иерархии/окне представления добавлены представления InputMethodService, и если они доступны из вашего процесса приложения/активности.
Источник для InputMethodService:
https://github.com/android/platform_frameworks_base/blob/master/core/java/android/inputmethodservice/InputMethodService.java
Источник для компоновки XML:
https://github.com/android/platform_frameworks_base/blob/master/core/res/res/layout/input_method_extract_view.xml
Если вы действительно хотите попасть в проблему, возможно, есть способ получить ссылку на службу IME и использовать отражение, чтобы изменить извлеченное представление. Стандартная InputMethodService
содержит частную ссылку на mExtractEditText
:)
Я не знаю ответа, который вы ищете, но, возможно, он поместит вас в правильном направлении... или в каком-то направлении.
Ответ 4
Если у вас есть один редактируемый элемент в диалоге, как насчет обработки изменений ориентации и
- в случае портретной ориентации, покажите диалог
- в случае ландшафтной ориентации, покажите полноэкранный фрагмент с помощью EditText и Buttons (как указывали другие, отключите полноэкранный режим редактирования для EditText), запросите фокус для EditText, покажите клавиатуру.
- в случае переключения ориентации отклонить Диалог/показать фрагмент с уже введенным текстом (и наоборот)
Это может быть концептуально хорошо, потому что если пользователь хочет ввести текст, он/она всегда будет в полноэкранном режиме редактирования в альбомной ориентации. И поскольку в исходном диалоге есть только один редактируемый вид, вам явно не нужен диалог, чтобы выбрать что-нибудь еще для редактирования (например, другой EditText).