Line break in AutoCompleteTextView

Issue

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"
/>

Solution

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.

Answered By – prosyanoy

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published