'Set width of TextInputEditText to n characters
I'm trying to implement a layout where user will input their phone number. The phone number will be 11 digits. And so I wanted to build a text input field with a fixed width that can accommodate 11 characters.
NOTE: I don't want the input field to be wider than 11 characters. Let's say each character is 10px wide. So the input field should be 11*10px = 110px wide (I'm not taking the drawable icon into account here).
Here's what I've tried in XML:
            <com.google.android.material.textfield.TextInputLayout
                android:id="@+id/textField"
                style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/margin_48"
                app:startIconDrawable="@drawable/ic_phone">
                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/phone"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:ems="11"
                    android:inputType="phone"
                    android:maxLength="11"
                    android:maxLines="1"
                    android:minEms="11"
                    android:text="01"
                    android:textSize="20sp"
                    android:typeface="monospace" />
            </com.google.android.material.textfield.TextInputLayout>
But this produces an output like the following:
As you can see, despite using ems and minEms, the field is 2 characters wide (it's 0 character wide if I don't add android:text). But I want it to have a width of 11 characters (not more or less). Why is ems not effective here and what's the solution?
Solution 1:[1]
Just edit your layout width
from
  android:layout_width="wrap_content"
to
   android:layout_width="match_parent"
I just edited your code
        <com.google.android.material.textfield.TextInputLayout
       
         android:id="@+id/textField"
                    
            
            
   style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/margin_48"
                    app:startIconDrawable="@drawable/ic_phone">
    
                    <com.google.android.material.textfield.TextInputEditText
                        android:id="@+id/phone"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:ems="11"
                        android:inputType="phone"
                        android:maxLength="11"
                        android:maxLines="1"
                        android:minEms="11"
                        android:text="01"
                        android:textSize="20sp"
                        android:typeface="monospace" />
                </com.google.android.material.textfield.TextInputLayout>
    					Solution 2:[2]
You should set a 11 digits monospace text in your TextInputEditText widget (for example 12345678901), then define a ViewTreeObserver.OnGlobalLayoutListener in your fragment, that calculates the width when the layout is available to be measured.
You could instantiate the observer in onResume() of your fragment, and remove it in onPause(). You should also store the width during the rotation of the activity.
Here below a full working example:
MainActivity.java:
public class MainActivity extends AppCompatActivity {
    ConstraintLayout constraintLayout;
    TextInputEditText textInputEditText;
    int viewWidth;
    ViewTreeObserver.OnGlobalLayoutListener viewTreeObserver = new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                constraintLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            } else {
                constraintLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
            viewWidth = textInputEditText.getMeasuredWidth();
            textInputEditText.setWidth(viewWidth);
            textInputEditText.setText("");
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (savedInstanceState != null) {
            viewWidth = savedInstanceState.getInt("viewWidth", 0);
        }
        constraintLayout = findViewById(R.id.id_constraintlayout);
        textInputEditText = findViewById(R.id.phone);
    }
    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putInt("viewWidth", viewWidth);
    }
    @Override
    public void onResume() {
        super.onResume();
        if (viewWidth == 0) {
            textInputEditText.setText("12345678901");
            ViewTreeObserver vto = constraintLayout.getViewTreeObserver();
            vto.addOnGlobalLayoutListener(viewTreeObserver);
        } else textInputEditText.setWidth(viewWidth);
    }
    @Override
    public void onPause() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
            constraintLayout.getViewTreeObserver().removeGlobalOnLayoutListener(viewTreeObserver);
        } else {
            constraintLayout.getViewTreeObserver().removeOnGlobalLayoutListener(viewTreeObserver);
        }
        super.onPause();
    }
}
activity_main.xml:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/id_constraintlayout"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/textField"
        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:startIconDrawable="@drawable/ic_phone">
        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/phone"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ems="11"
            android:inputType="phone"
            android:maxLength="11"
            android:maxLines="1"
            android:minEms="11"
            android:textSize="20sp"
            android:typeface="monospace" />
    </com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
I enclose an image of the result here below, where I already typed 6 digits:
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | Anandh Krishnan | 
| Solution 2 | 


