2016-05-24 2 views
0

Как создать дополнительную строку (подчеркивание) в TextView?textview underline (дополнительный текст)

Например

line1:

|word1  word2  word3 word4| //size17 

|  word2 description   | //size 6 

line2:

|word4 word5 word6  word7  | //size17 

|    word7 description | //size6 

EDIT 27,05:

предварительная версия. Любые идеи по улучшению?

public class DescriptionSpan extends ReplacementSpan { 


String description; 
Paint descriptionPaint; 

public DescriptionSpan(Paint paint, String description) { 
    descriptionPaint = paint; 
    this.description = description; 
} 


@Override 
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { 

    float delta = getShift(paint, text.subSequence(start, end).toString(), description); 

    if (delta >= 0) { 
     canvas.drawText(text, start, end, x, y, paint); 
     canvas.drawText(description, 0, description.length(), x + delta, y + descriptionPaint.getTextSize(), descriptionPaint); 
    } else { 
     canvas.drawText(text, start, end, x - delta, y, paint); 
     canvas.drawText(description, 0, description.length(), x, y + descriptionPaint.getTextSize(), descriptionPaint); 
    } 
} 

@Override 
public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { 
    return (int) Math.max(paint.measureText(text, start, end), descriptionPaint.measureText(description)); 
} 


private float getShift(Paint paint, String text, String description) { 
    return (paint.measureText(text) - descriptionPaint.measureText(description))/2; 
} 

Похоже, что ваше сообщение в основном кода; пожалуйста, добавьте более подробную информацию ....

+0

Я предполагаю, что вы не имеете в виду, что это сетка текстов, вы имеете в виду, что это слова в строках абзаца, и под обозначенным словом вы хотите получить дополнительный текст под этим словом. Это точно? Возможно, вы могли бы сказать еще немного о том, что вы делаете с этим текстовым дисплеем. –

+0

есть. В основном необходимо описание вокруг (сверху или снизу) слова –

+1

Для этого потребуется, по крайней мере, индивидуальный подкласс Span. Я посмотрю на это. Если бы кто-то дал мне это код, я бы подумал о создании пользовательского представления и сделать все текстовые измерения/вычисления/рендеринг напрямую. –

ответ

0

Для этого вы можете использовать SpannableStringBuilder. Что-то вроде ниже:

SpannableStringBuilder span = new SpannableStringBuilder(); 
    span.append("First Line"); 
    span.setSpan(new RelativeSizeSpan(.8f),0,firstLineLength); 
    span.append("Second Line"); 
    span.setSpan(new RelativeSizeSpan(1f),firstLineLength,firstLineLength+secondLineLength); 
textView.setText(span); 
+0

В настоящее время решение создало текст как cCcCcCcC. Вычисление позиции для описания выглядит сложным для разных многострочных текстов. –

1

Мне не нравится писать ответы без кода; однако я слишком долго занимался этим (я не могу устоять перед проблемой, когда речь заходит о кодировании), и я думаю, что у меня достаточно информации, чтобы привести вас в правильном направлении без примера рабочего кода.

Путь это должен работать в том, что в getSize() вы бы установить FontMetricsInt, которые передаваемые в надлежащей высоту для пролета, а также вернуть ширину диапазона.

Но вот вещь: только конкретная реализация ReplacementSpan является ImageSpan, которая проходит DynamicDrawableSpan (который является ReplacementSpan). Если вы посмотрите на DynamicDrawableSpan, он устанавливает нисходящее и нижнее значение в ноль, а всплытие и верхние к размеру вытягиваемого. Подробнее об этом через секунду.

Когда я взял ваш код и попытался добавить логику метрик шрифта в getSize(), я столкнулся с несколькими проблемами.

  1. Изменение подъем/верхней почитается, но любое изменение в нижнюю часть - которые должны были бы скорректированным, чтобы места для Вашего описания - это не честь. Похоже, что логика адаптирована для размещения ImageSpan/DynamicDrawableSpan, а все остальное рассматривается как непроверенный угловой случай.

  2. ReplacementSpan, похоже, предназначен для однострочных текстов. Восхождение & вверху правильно настроены в строке первого абзаца, но после обертывания линии восстанавливается нормальное восхождение/верх.

  3. Пролет обычно рассматривается как неразрывное слово, но я столкнулся с прерывистой ошибкой, когда сам по себе был обернут вторую строку. Очевидно, что это будет проблемой при расчете, где разместить все ваши тексты.

Так что, если вы действительно хотите сделать это с пролетами, я думаю, что вы должны сделать, это еще один пролет пользовательского пункта в стиле, который реализует LineHeightSpan. Для этого вы бы использовали chooseHeight().Как это работает, так как для каждой строки в абзаце будет вызываться chooseHeight(). Ваша реализация будет искать DescriptionSpan на этой строке и установить метрики шрифта для размещения текста описания. Таким образом, вы будете обертывать каждый абзац, который имел бы DescriptionSpan с этим абзацем. С этим диапазоном ваш DescriptionSpan не изменит метрики шрифтов в getSize(), и вы просто предположите, что у вас есть место для текста описания в draw(). (Я надеюсь, что холст не привязан к границам диапазона. Эта пользовательская идея представления просто продолжает выглядеть лучше и лучше.)

Я бы хотел, чтобы код работал и опубликовал его, но я трачу слишком много времени, head на ReplacementSpan метрик шрифта.

+0

Да, я знаю. В свободное время я попытаюсь расширить это решение. Для текущей задачи достаточно (слово/перевод не занимают много места, дополнительное пространство by lineSpacingMultiplier). Я не хочу использовать custome view. Я думаю, что будет достаточно добавить что-то вроде [numberLine = measure/lineLenght +1; FontMetricsInt.bottom * numberLine; foreach draw line] –