Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use a custom font in the input area of an input method?

We're developing an app where we need to use a custom font (a Typeface loaded from the app's assets) in an EditText. The Android input method docs state the following:

When input focus moves into or out of an editable text field, Android shows or hides the input method (such as the on-screen keyboard) as appropriate. The system also makes decisions about how your UI and the text field appear above the input method. For example, when the vertical space on the screen is constrained, the text field might fill all space above the input method.

It's the part in bold that is tripping us up. The phrase “the text field might fill...” appears to be misleading, in that the text field that's used is not the EditText that we set up with our custom font. (NOTE: the answers so far all explain how to set a custom font in an EditText. We already are setting a custom typeface in the EditText. Please read the question carefully before answering.) Here's a screenshot with the input method hidden:

the dialog

Here's what happens when the soft keyboard is showing and vertical space is constrained:

constrained vertical space

As you can see, the font in the text field above the input method is not our custom font (I'm guessing it's the system's default Roboto font). This is happening for every soft keyboard we've tried as the input method.

I want to emphasize that when space is constrained, this view above the keyboard is generated internally by the system, not by any of our code.

The main question is: Is there a way (and, if so, what is it?) to control the appearance of this (for lack of better terminology) proxy view—at a minimum to get it to use our custom font?

It would be an added bonus if we could also control the layout and appearance of the entire proxy area above the keyboard (including the "Done" button). We are using a variation of the technique described in this thread to have our activity use a locale different from the one set in the system, but the activity's locale clearly isn't being applied here. (If it were, the button would be on the left and would read "בוצע", as does happen if I change the device's locale to Hebrew. [EDIT: I can get the correct button label by using the android:imeActionLabel attribute on the EditText. However, I don't know how to control the layout directionality.])

EDIT Per request, here's how I'm constructing my dialog (relevant parts excerpted from a 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.)
}

And here's the layout:

<?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>
like image 869
Ted Hopp Avatar asked Sep 10 '14 03:09

Ted Hopp


People also ask

How do you change the font on an input tag?

To change the font size in HTML, use the style attribute. The style attribute specifies an inline style for an element. The attribute is used with the HTML <p> tag, with the CSS property font-size. HTML5 do not support the <font> tag, so the CSS style is used to add font size.


1 Answers

It would be simple if you had an instance of InputMethodService. There is a way to set a theme or even set extracted view.

The problem is you have to create a custom implementation of Input Method and users will have to select it in the system settings.

Update:

You can try with:

    • android:windowSoftInputMode="adjustResize"
    • make the view scrollable

or

    • use IME_FLAG_NO_EXTRACT_UI
    • set an OnEditorActionListener on the EditText to have an action button on the keyboard.
    • create custom layout or hide/show elements when screen's height is too small. For example hide buttons at the bottom and show buttons on right side. It can look similar to the default extract view.

layout listener for the dialog or 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);                    
            }
        }
    });

Changing the visibility to GONE will request relayout and the listener will run again what can lead to a loop.

like image 61
pawelzieba Avatar answered Oct 29 '22 13:10

pawelzieba