Line break in AutoCompleteTextView

Viewed 102

I have looked through plenty of sources trying to find how to break the text in a dropdown item into two lines, so that is could be shown fully, but unfortunately I haven't found any solution.

Instead, only the beginning of the string is shown, and it ends with ellipsis.

Here is my code in LoginActivity:

autoSuggestAdapter = AutoSuggestAdapter(
        this,
        R.layout.abc
    )
    autoCompleteTextView.threshold = 2
    autoCompleteTextView.setAdapter(autoSuggestAdapter)
    autoCompleteTextView.onItemClickListener =
        OnItemClickListener { parent, view, position, id ->
            selectedText.text = autoSuggestAdapter!!.getObject(position)
        }

    handler = Handler(Looper.getMainLooper(), Handler.Callback { msg ->
        if (msg.what === TRIGGER_AUTO_COMPLETE) {
            if (!TextUtils.isEmpty(autoCompleteTextView.text)) {
                makeApiCall(autoCompleteTextView.text.toString())
            }
        }
            false
        }
    )

class AutoSuggestAdapter

class AutoSuggestAdapter(context: Context, resource: Int) :
ArrayAdapter<String>(context, resource), Filterable {
private val mlistData: MutableList<String>
fun setData(list: List<String>?) {
    mlistData.clear()
    mlistData.addAll(list!!)

}

override fun getCount(): Int {
    return mlistData.size
}

@Nullable
override fun getItem(position: Int): String {
    return mlistData[position]
}

fun getObject(position: Int): String {
    return mlistData[position]
}

override fun getFilter(): Filter {
    return object : Filter() {
        protected override fun performFiltering(constraint: CharSequence?): FilterResults {
            val filterResults = FilterResults()
            if (constraint != null) {
                filterResults.values = mlistData
                filterResults.count = mlistData.size
            }
            return filterResults
        }

        protected override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
            if (results != null && results.count > 0) {
                notifyDataSetChanged()
            } else {
                notifyDataSetInvalidated()
            }
        }
    }
}

init {
    mlistData = ArrayList()
}

abc.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:ellipsize="end"
android:maxLines="2"
android:lines="2"
android:textAppearance="?attr/textAppearanceSubtitle1"
/>
2 Answers

I managed to solve the issue by overriding getView function in my AutoSuggestAdapter.

override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
    val view: TextView = convertView as TextView? ?: LayoutInflater.from(context).inflate(layoutResource, parent, false) as TextView
    var r = mlistData[position]
    // ...
    return view
}

For line break, there is a specific android class, but I couldn't use it in Kotlin. Besides, it is supported only in API 29 and higher. So I wrote the following code that inspects spaces across the string and checks whether the current line exceeds the width of the screen or not:

override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
    val view: TextView = convertView as TextView? ?: LayoutInflater.from(context).inflate(layoutResource, parent, false) as TextView
    var r = mlistData[position]

    paint.textSize = scaledPx

    var k = -1
    var n = -1
    var str = ""
    while (k < r.length) {
        if (r.indexOf(" ", k+1) == -1) {
            if (paint.measureText(r.substring(n+1, r.length)) > widthPixels) {
                var line1 = r.substring(n+1, k)
                var line2 = r.substring(k+1, r.length)
                str = "$str$line1\n$line2"
            } else {
                var line = r.substring(n+1, r.length)
                str = "$str$line"
            }
            break
        } else {
            if (paint.measureText(r.substring(n+1, r.indexOf(" ", k+1))) > widthPixels) {
                var line = r.substring(n+1, k)
                n = k
                str = "$str$line\n"
            } else {
                k = r.indexOf(" ", k+1)
            }
        }
    }
    view.text = str.substring(0, str.length)
    return view
}

Future improvements might be implementing some kind of word wrap. Any suggestions are appreciated.

To get a TextView to show multiple lines without ellipsis I do the following

// Work around to wrap single line text in textview/edittext
// these don't seem to work in the xml
        textView.setHorizontallyScrolling(false);
        textView.setMaxLines(2);

I note that you've tried setMaxlines already but from experience this does not seem to work when set in an xml file, it has to be set programmatically along with disabling Horizontally Scrolling

Shown below on a 2 line edittext wrapped with no ellipsis enter image description here

Related