Сделайте определенную часть андроида-textview вправо
У меня есть это TextView
. Некоторые его части должны быть выровнены влево, а некоторые - вправо. Как мне это сделать на Java?
В основном я хочу, чтобы первая строка выравнивалась влево, а следующая строка - вправо и т.д.
Кто-нибудь понял?
ИЗМЕНИТЬ
Я попытался использовать HTML, а затем, когда это не помогло, я пробовал пробелы.
html попытка
textView.setText(Html.fromHtml("<p align=\"right\">THIS IS TO THE RIGHT</p>"));
И вот попытка пролета
String LeftText = "LEFT";
String RightText = "RIGHT";
final String resultText = LeftText + " " + RightText;
final SpannableString styledResultText = new SpannableString(resultText);
styledResultText.setSpan(new AlignmentSpan.Standard(Alignment.ALIGN_OPPOSITE), LeftText.length() + 1, LeftText.length() + 2 +RightText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(styledResultText);
Но никто из них не работает.
Ответы
Ответ 1
TextView resultTextView = new TextView(this);
final String resultText = LeftText + " " + RightText;
final SpannableString styledResultText = new SpannableString(resultText);
styledResultText.setSpan(new AlignmentSpan.Standard(Alignment.ALIGN_OPPOSITE)
, LeftText.length() + 2
, LeftText.length() + 2 + RightText.length()
, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
resultTextView.setText(styledResultText);
Alignment.ALIGN_OPPOSITE is the equivalent for right side.
Alignment.ALIGN_NORMAL is the equivalent for left side.
Ответ 2
Вот решение, которое работает с Spannable, с каватетом, если справа и слева слишком широкие, они будут перекрываться на одной линии. Поскольку для выполнения левого/правого трюка с помощью spannable требуется прямая линия между Left и Right, мое исправление заключается в добавлении spannable, который уменьшает высоту линии до нуля (т.е. перекрывающиеся линии) для одного перевода строки, а затем восстанавливает нормальную высоту линии после что.
String fullText = leftText + "\n " + rightText; // only works if linefeed between them! "\n ";
int fullTextLength = fullText.length();
int leftEnd = leftText.length();
int rightTextLength = rightText.length();
final SpannableString s = new SpannableString(fullText);
AlignmentSpan alignmentSpan = new AlignmentSpan.Standard(Layout.Alignment.ALIGN_OPPOSITE);
s.setSpan(alignmentSpan, leftEnd, fullTextLength, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
s.setSpan(new SetLineOverlap(true), 1, fullTextLength-2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
s.setSpan(new SetLineOverlap(false), fullTextLength-1, fullTextLength, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
И у нас есть небольшая подпрограмма для обработки перекрывающихся строк:
private static class SetLineOverlap implements LineHeightSpan {
private int originalBottom = 15; // init value ignored
private int originalDescent = 13; // init value ignored
private Boolean overlap; // saved state
private Boolean overlapSaved = false; // ensure saved values only happen once
SetLineOverlap(Boolean overlap) {
this.overlap = overlap;
}
@Override
public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int v,
Paint.FontMetricsInt fm) {
if (overlap) {
if (!overlapSaved) {
originalBottom = fm.bottom;
originalDescent = fm.descent;
overlapSaved = true;
}
fm.bottom += fm.top;
fm.descent += fm.top;
} else {
// restore saved values
fm.bottom = originalBottom;
fm.descent = originalDescent;
overlapSaved = false;
}
}
}
Ответ 3
Спасибо за подсказку @Frank, но этого было достаточно:
public class LineOverlapSpan implements LineHeightSpan {
@Override
public void chooseHeight(final CharSequence text, final int start, final int end, final int spanstartv, final int v, final Paint.FontMetricsInt fm) {
fm.bottom += fm.top;
fm.descent += fm.top;
}
}
Используется следующим образом:
CharSequence text = return new Truss()
.append("LEFT")
.pushSpan(LineOverlapSpan())
.append("\n")
.popSpan()
.pushSpan(AlignmentSpan.Standard(Layout.Alignment.ALIGN_OPPOSITE))
.append("RIGHT")
.build()
где Truss
есть
A SpannableStringBuilder
обертка, API которой не заставляет меня хотеть ударить глазами.
Ответ 4
Два решения:
1) имеют различный текстовый вид для каждой строки и устанавливают его гравитацию.
2) Используйте Html во время загрузки данных, устанавливая выравнивание в html для него REF: how-to-display-html-in-textview Это не сработает align не поддерживает тегиОтредактировано:
Кроме
3: будет использовать диапазон.
Ответ 5
Простой .Adjust xml part в textview. Используйте layouts.Если вы хотите, чтобы textview находился в левом
android: alignParentLeft = "true". Для получения более подробной информации смотрите это.
http://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams.html
И это также пример для разных макетов.
http://www.androidhive.info/2011/07/android-layouts-linear-layout-relative-layout-and-table-layout/
Ответ 6
Вдохновили другие решения, но решили проблемы многострочного текста и проблемы с перекрытием текста.
class LineOverlapSpan() : LineHeightSpan {
var originalBottom: Int = 0
var originalDescent: Int = 0
var overlapSaved = false
override fun chooseHeight(
text: CharSequence?,
start: Int,
end: Int,
spanstartv: Int,
v: Int,
fm: Paint.FontMetricsInt?
) {
if (fm == null) {
return
}
if (!overlapSaved) {
originalBottom = fm.bottom
originalDescent = fm.descent
overlapSaved = true
}
if (text?.subSequence(start, end)?.endsWith("\n") == true) {
fm.bottom += fm.top
fm.descent += fm.top
} else {
fm.bottom = originalBottom
fm.descent = originalDescent
}
}
}
Использование:
fun keyValueSpan(key: CharSequence, value: CharSequence) = span {
span {
alignment = "normal"
+key
span {
textColor = Color.TRANSPARENT
+value
}
span {
+"\n"
addSpan(LineOverlapSpan())
}
}
span {
alignment = "opposite"
+value
}
}
Решение Kotlin использует библиотеку Kpan https://github.com/2dxgujun/Kpan