Android TextVIew Многоточие в зависимости от размера представления

Я пытаюсь установить многоточие в конец моего текста (многострочного), если текст слишком длинный.

Я уже знаю, что могу использовать setMaxLines() и setEllipsize() для достижения эффекта. Однако, поскольку размер моего текстового представления динамически изменяется, я не знаю максимальное количество отображаемых строк. Вместо этого у меня есть высота текста (по пикселям).

Как установить многоточие на основе высоты представления и текста (включая свойства шрифта)? Если нет прямого доступного ресурса, который я могу использовать, какой может быть самый простой подход?


person yongsunCN    schedule 12.08.2015    source источник


Ответы (2)


Вы можете использовать getLineCount() (но только после прохода макета).

См. этот ответ для получения дополнительной информации.

person Buddy    schedule 12.08.2015
comment
getLineCount() не будет работать, потому что текстовое представление может вырасти с маленькой высоты на большую. если я устанавливаю максимальный номер строки, когда высота маленькая, getLineCount всегда будет возвращать старое небольшое число, когда высота увеличивается. Таким образом, максимальный номер строки не обновляется. Кроме того, установка максимального номера строки запланирует проход макета, что не является моим желанием. Спасибо за ваш ответ. - person yongsunCN; 13.08.2015

Я реализовал это, используя концепцию этого ответа.

Вы можете создать функцию расширения, подобную этой:

/**
 * Calculate max lines according height
 *
 * @param text- text need to be set
 * @param lineCount- invoked with -1 if view height is enough to show full text,
 *                   otherwise invoked with maxLines
 */
inline fun TextView.calculateMaxLines(text: String, crossinline lineCount: (Int) -> (Unit)) {
    val params: PrecomputedTextCompat.Params = TextViewCompat.getTextMetricsParams(this)
    val ref: WeakReference<TextView>? = WeakReference(this)
    GlobalScope.launch(Dispatchers.Default) {
        val computedText = PrecomputedTextCompat.create(text, params)
        ref?.get()?.apply {
            TextViewCompat.setPrecomputedText(this, computedText)
            GlobalScope.launch(Dispatchers.Main) {
                ref.get()?.let {
                    val bounds = it.getLineBounds(0, null)
                    val heightRequired = bounds * it.lineCount
                    val maxLines = if (heightRequired > height) {
                        height / bounds
                    } else -1
                    lineCount.invoke(maxLines)
                }
            }
        }
    }
}

Затем вы можете вызвать его и установить maxLines следующим образом:

textView.calculateMaxLines("Line 1\nLine2\nLine3\nLine4\nLine5\nLine6\nLine7\nLine8") {
            if (it >= 0) {
                tvUserName.maxLines = it
                tvUserName.ellipsize = TextUtils.TruncateAt.END
            }
        }

Или для Java вы можете назвать это так:

ExtensionsKt.calculateMaxLines(textView, text, maxLines -> {
            if (maxLines >= 0) {
                textView.setMaxLines(maxLines);
                textView.setEllipsize(TextUtils.TruncateAt.END);
            }
            return null;
        });
person Barno    schedule 26.05.2020