¿Cómo puedo utilizar una fuente personalizada en el área de entrada de un método de entrada?

Estamos desarrollando una aplicación en la que debemos utilizar una fuente personalizada (un Typeface cargado desde los recursos de la aplicación) en un EditText . El método de introducción de datos de Android indica lo siguiente:

Cuando el foco de entrada se mueve dentro o fuera de un campo de texto editable, Android muestra u oculta el método de entrada (como el teclado en pantalla) según corresponda. El sistema también toma decisiones sobre cómo aparece la interfaz de usuario y el campo de texto por encima del método de entrada. Por ejemplo, cuando el espacio vertical en la pantalla está restringido, el campo de texto podría llenar todo el espacio sobre el método de entrada.

Es la parte en negrita que nos está tropezando. La frase "el campo de texto podría llenar …" parece ser engañosa, en que el campo de texto que se utiliza no es el EditText que configuramos con nuestra fuente personalizada. ( NOTA: las respuestas hasta ahora todos explican cómo establecer una fuente personalizada en un EditText estamos configurando un tipo de letra personalizado en el EditText la pregunta cuidadosamente antes de responder.) Aquí hay una captura de pantalla con el método de entrada oculto:

El diálogo

Esto es lo que ocurre cuando se muestra el teclado virtual y se limita el espacio vertical:

Espacio vertical restringido

Como puede ver, la fuente en el campo de texto sobre el método de entrada no es nuestra fuente personalizada (supongo que es la fuente Roboto del sistema). Esto está sucediendo para cada teclado suave que hemos probado como el método de entrada.

Quiero enfatizar que cuando el espacio está restringido, esta vista sobre el teclado es generada internamente por el sistema, no por ninguno de nuestros códigos.

La pregunta principal es: ¿Existe una manera (y, si es así, ¿qué es?) Para controlar la apariencia de esta (por falta de mejor terminología) de la vista de proxy, como mínimo para que use nuestra fuente personalizada?

Sería un bono adicional si también pudiéramos controlar el diseño y la apariencia de todo el área de proxy por encima del teclado (incluido el botón "Listo"). Utilizamos una variante de la técnica descrita en este subproceso para que nuestra actividad utilice una configuración regional distinta a la establecida en el sistema, pero no se aplica aquí la configuración regional de la actividad. (Si lo fuera, el botón estaría a la izquierda y leería "בוצע", ​​como ocurre si cambio la configuración del dispositivo en hebreo. [EDIT: Puedo obtener la etiqueta del botón correcto usando el atributo android:imeActionLabel en el EditText Sin embargo, no sé cómo controlar la direccionalidad de diseño.])

EDIT Por solicitud, he aquí cómo construyo mi diálogo (partes relevantes extraídas de un 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.) } 

Y aquí está el diseño:

 <?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> 

Sería sencillo si tuviera una instancia de InputMethodService. Hay una manera de establecer un tema o incluso establecer la vista extraída .

El problema es que hay que crear una implementación personalizada del método de entrada y los usuarios tendrán que seleccionarla en la configuración del sistema.

Actualizar:

Puede probar con:

    • android:windowSoftInputMode="adjustResize"
    • Hacer la vista desplazable

o

    • Utilice IME_FLAG_NO_EXTRACT_UI
    • OnEditorActionListener un OnEditorActionListener en el EditText para tener un botón de acción en el teclado.
    • Crear diseños personalizados o ocultar / mostrar elementos cuando la altura de la pantalla es demasiado pequeña. Por ejemplo ocultar los botones en la parte inferior y mostrar los botones en el lado derecho. Puede parecer similar a la vista de extracto predeterminada.

Listener para el diálogo o 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); } } }); 

Cambiar la visibilidad a GONE pedirá relayout y el oyente se ejecutará de nuevo lo que puede conducir a un bucle.

La única manera que puedo ver es deshabilitar el modo de edición de pantalla completa para su EditText que se activa automáticamente cuando su EditText no es lo suficientemente alto.

 mNoteEditor.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI); 

Puede solucionar los problemas de cambio de

 dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); 

Su diseño de diálogo probablemente debería estar encerrado en un ScrollView .

Creo que como otros han dicho esto es, por desgracia, el IME y no puede ser posible a través de APIs compatibles.

Tenga cuidado, hacky y no probado solución entrante:

Explorando el código fuente de Android, descubrí que cada IME contiene una implementación de AbstractInputMethodService . Android proporciona una implementación estándar ( android.inputmethodservice.InputMethodService ) que si miras, tiene un método public setExtractView y un método onCreateExtractTextView , que infla com.android.internal.R.layout.input_method_extract_view.xml , que a su vez contiene com.android.internal.R.id.inputExtractEditText ! Así que una solución hacky sería esperar que la mayoría de los IMEs de sus clientes InputMethodServices utilizar este mismo XML (que por lo que puedo decir, ha estado en Android por un tiempo), y usted puede intentar agarrar una referencia a este EditText por Es ID y cambia su tipografía. Lamentablemente, no estoy seguro de que en la jerarquía de vista / ventana se agregan las vistas de un InputMethodService, y si son accesibles desde su proceso de aplicación / actividades.

Fuente para InputMethodService: https://github.com/android/platform_frameworks_base/blob/master/core/java/android/inputmethodservice/InputMethodService.java

Fuente para la disposición XML: https://github.com/android/platform_frameworks_base/blob/master/core/res/res/layout/input_method_extract_view.xml

Si realmente quiere meterse en problemas, quizás haya una manera de obtener una referencia al servicio IME en sí, y usar la reflexión para alterar la vista extraída. El InputMethodService estándar contiene una referencia privada de paquete a mExtractEditText 🙂

No sé la respuesta que estás buscando, pero tal vez te pondrá en la dirección correcta … o en alguna dirección al menos.

Si tiene un solo elemento editable en su Diálogo, ¿cómo manejar cambios de orientación y

  • En el caso de orientación vertical, muestre el diálogo
  • En el caso de la orientación horizontal, mostrar un fragmento de pantalla completa con el EditText y los botones (como otros han declarado, desactivar el modo de edición de pantalla completa para el EditText), el foco de solicitud para el EditText, mostrar el teclado.
  • En caso de cambio de orientación desconectado Diálogo / show Fragmento con el texto ya introducido (y viceversa)

Esto puede ser conceptualmente bueno porque si el usuario desea introducir texto, él / ella siempre terminará en un diseño de edición en pantalla completa en orientación horizontal. Y puesto que sólo hay una vista editable en el cuadro de diálogo original, no necesita explícitamente el cuadro de diálogo para seleccionar otra cosa para editar (otro EditarTexto, por ejemplo).

  • Android enviar imagen con teclado
  • Botón de acción de teclado suave de Android
  • Android SearchView Ocultar el teclado al iniciar
  • Softkeyboard oculta botón debajo de varias líneas EditText?
  • Retener soft-input / IME state en el cambio de orientación
  • Cómo configurar diferentes fondos de claves para Android Custom Keyboard
  • Botón predeterminado emoji en el teclado de Google con android 4.4
  • El teclado webview android no aparece durante mucho tiempo para introducir valores
  • Cómo mostrar el teclado virtual cuando edittext está enfocado
  • AlertDialog con EditText, abre el teclado virtual automáticamente con el enfoque en EditText no funciona
  • ¿Cómo ocultar el teclado suave desde el interior de un fragmento?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.