4

I have a layout in which an EditText is filled by the user, then later on it becomes disabled to act as standard TextView.

Problem is, the ellipsize never works on this EditText. I'd like it to display "..." at the end of the text when it is too large to be displayed completely, but I can't find any way to make it works, and I have no idea why it doesn't.

Here is my layout

<RelativeLayout
android:id="@+id/search_container"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_below="@+id/toolbar"
android:background="@drawable/bg_border_bot_clickable"
android:addStatesFromChildren="@+id/ic_edit"
android:animateLayoutChanges="true">

    <View
        android:layout_width="45dp"
        android:layout_height="45dp"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="5dp"
        android:layout_alignParentLeft="true"
        android:background="@drawable/ic_action_search"
        android:id="@+id/ic_search" />

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:textColorHint="@color/text_hint"
        android:hint="@string/search_hint"
        android:id="@+id/et_search"
        android:textColor="@android:color/white"
        android:inputType="text|textCapSentences"
        android:ellipsize="end"
        android:singleLine="true"
        android:lines="1"
        android:imeOptions="actionSearch"
        android:background="@drawable/transition_rounded_rectangle"
        android:layout_toLeftOf="@+id/ic_edit"
        android:layout_toRightOf="@+id/ic_search"
        />

<View
    android:layout_width="45dp"
    android:layout_height="45dp"
    android:layout_centerVertical="true"
    android:layout_alignParentRight="true"
    android:background="@drawable/ic_edit"
    android:id="@+id/ic_edit"
    android:visibility="gone"
    android:clickable="true"/>

Any ideas on how to accomplish that?

Euporie
  • 1,896
  • 1
  • 21
  • 23
Gyome
  • 1,333
  • 2
  • 15
  • 23

5 Answers5

8

Add the following attributes to your EditText to wrap the content with ellipsis.

android:scrollHorizontally="true"
android:ellipsize="end"
android:singleLine="true"
android:editable="false"

if you don't want to set editable to false by default in your XML, you can achieve the same result by calling setKeyListener(null).

editText.setKeyListener(null);
Christian Abella
  • 5,747
  • 2
  • 30
  • 42
  • 1
    setting the key listener to null works! Thank you. Honestly I did not believe it, but I guess that makes some sort of sense. – Gyome May 06 '15 at 14:15
  • This works great! Additionally, to make it usable as an input field: hold onto the KeyListener after creating the view and set/remove it in an OnFocusChanged listener. – dwemthy Nov 14 '17 at 17:17
  • 1
    @ChristianAbella, thank you. Your tip (`editText.keyListener = null`) is working great for me (Android API 23+). I just added a few algorithms because I need the `EditText` to work again without the ellipses as soon as the user returns focus to the field. – Thiengo Jan 09 '23 at 22:56
4

This is my solution(I've worked it out):

xml:

<androidx.appcompat.widget.AppCompatEditText
    android:id="@+id/et2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:layout_marginHorizontal="10dp"
    android:layout_marginTop="10dp"
    android:background="@drawable/selector_btn_check_red_grey"
    android:hint="Please enter characters"
    android:inputType="text"
    android:lines="1"
    android:paddingHorizontal="10dp"
    android:paddingVertical="5dp"
    android:text="就会角度打开的事开发的急啊看手机发就卡的房多少"
    android:textAllCaps="false"
    android:textColor="@color/red_500"
    android:textSize="15sp" />

java:

    //Initialize to non-editable state
    et2.setKeyListener(null);
    et2.setEllipsize(TextUtils.TruncateAt.END);//setEllipsize只对hint有效果

    et2.setOnFocusChangeListener((v, hasFocus) -> {
        if (hasFocus) {
            //Editable status
            et2.setEllipsize(null);
            et2.setKeyListener(new TextKeyListener(TextKeyListener.Capitalize.NONE, false));
        } else {
            //Not editable[enter image description here][1]
            et2.setKeyListener(null);
            et2.setEllipsize(TextUtils.TruncateAt.END);
        }
    });
sindi.chen
  • 41
  • 1
2

I think ellipsize does not work with EditText. One way to work around this is to have a TextView with ellipsize below your EditText. Initially set TextView visibility to GONE. When you want to disable the EditText, set its visibility to GONE, assign the text to the TextView and set TextView visibility to VISIBLE.

Tony Vu
  • 4,251
  • 3
  • 31
  • 38
0

As you already used :

android:ellipsize="end"

One more thing you should add. Call setSeleted(true) from your java file

EditText edit = (EditText) findViewById(R.id.editTextId);
edit.setSelected(true);

Give id editTextId to your EditText ;

 <EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/editTextId" />
Kushal
  • 8,100
  • 9
  • 63
  • 82
0

After some numerous tests, including the use of the AppCompatEditText API, I can say that @ChristianAbela solution was without a doubt the one that worked without problems in a scenario where the project should support Android versions starting from API 23 (Android Marshmallow).

In my case I should also make the field, EditText, go back to normal (editText.keyListener != null) as soon as the user returns focus to the field.

So, if you can't leave the EditText locked but still need to present an ellipsis, then the following code strategy may be useful.

1 - Support class

First I build all the field status hackcode into a support class:

import android.text.method.KeyListener
import android.widget.EditText

/**
 * The purpose of this class is to allow saving the status of the fields
 * present in the "Search estimate" page.
 *
 * Thus, it is possible to use a business logic where the fields present
 * on this page show, when there is large content, ellipsis indicating
 * that the content is even larger.
 */
class FieldDataStatusHolder {

    private var procedureFieldText: String = ""
    private var procedureFieldKeyListener: KeyListener? = null

    private var locationFieldText: String = ""
    private var locationFieldKeyListener: KeyListener? = null

    fun holdData(
        unfocusedField: EditText,
        procedureField: EditText
    ) {
        if (unfocusedField == procedureField) {
            procedureFieldText = unfocusedField.text.toString()
            procedureFieldKeyListener = unfocusedField.keyListener
        } else {
            locationFieldText = unfocusedField.text.toString()
            locationFieldKeyListener = unfocusedField.keyListener
        }

        /**
         * This binding to null is necessary because this is the core of
         * the hackcode. This makes the editable View (EditText or
         * subclasses) no longer editable and so the ellipses appear at
         * the end of the field.
         */
        unfocusedField.keyListener = null
    }

    fun retrieveHoldenData(
        focusedField: EditText,
        procedureField: EditText
    ) {
        if (focusedField == procedureField && procedureFieldKeyListener != null) {
            focusedField.keyListener = procedureFieldKeyListener

            if (focusedField.text.isNotEmpty()) {
                focusedField.setText(procedureFieldText)
            }
        } else if (locationFieldKeyListener != null) {
            focusedField.keyListener = locationFieldKeyListener

            if (focusedField.text.isNotEmpty()) {
                focusedField.setText(locationFieldText)
            }
        }
    }
}

In the code above, don't be confused by properties and variables containing prefixes or suffixes like "Procedure" and "Location".

That's because these are labels referring to the problem domain I was applying the code to.

I had two fields on screen, "Search procedure" and "Search Location".

As soon as the user removes focus from one or both fields, if the field's content is longer than the field itself, then the ellipsis should appear at the end of the visual component.

2 - Hackcode instance declaration

In the client class I added the declaration lazily (but you can proceed as you wish) and in class scope and not in function scope:

private val fieldDataStatusHolder by lazy {
    FieldDataStatusHolder()
}

3 - Execution on OnFocusChangeListener

So it was necessary to add the logical execution of the FieldDataStatusHolder instance in the OnFocusChangeListener generator method that I had already created:

private fun getFieldFocusChangeListener() = View.OnFocusChangeListener { view, hasFocus ->
    
    // I do have lots of more domain code here.

    if (hasFocus) {
        fieldDataStatusHolder.retrieveHoldenData(
            focusedField = view as EditText,
            procedureField = etProcedureField
        )
    } else {
        fieldDataStatusHolder.holdData(
            unfocusedField = view as EditText,
            procedureField = etProcedureField
        )
    }
}

This method is used as follows to initialize listeners on fields:

etProcedureField.onFocusChangeListener = getFieldFocusChangeListener()
etLocationField.onFocusChangeListener = getFieldFocusChangeListener()

4 - Views in XML

Finally, it was necessary to add the attributes and values below to the EditTexts:

  • android:ellipsize="end";
  • android:maxLines="1".

Note that even for Android 23 I didn't need the following attributes:

  • android:singleLine (deprecated);
  • android:scrollHorizontally.

Another important point is… I am actually using the following visual components for each field:

  • TextInputLayout;
  • TextInputEditText.

And the TextInputLayout component contains an endIcon. Therefore, every time the field loses focus, so that the ellipsis appears (Android API 31+), I also hide the endIcon.

But that's an algorithm I won't add here to avoid making the answer even more verbose.

And yes, the code here should work not only for EditText, but for any its subclass as well.

Results

Field with focus:

enter image description here

Field without focus:

enter image description here

Thiengo
  • 226
  • 1
  • 3
  • 33