Java 使android textview的某个部分向右对齐

Java 使android textview的某个部分向右对齐,java,android,android-widget,Java,Android,Android Widget,我有这个TextView。它的一些部分应该向左对齐,一些部分应该向右对齐。在Java中如何实现这一点 基本上,我希望第一行向左对齐,下一行向右对齐,依此类推 有人有线索吗 编辑 我曾经尝试过使用HTML,但当它不起作用时,我尝试了使用spans html尝试 textView.setText(Html.fromHtml("<p align=\"right\">THIS IS TO THE RIGHT</p>")); 但它们似乎都不起作用。两种解决方案: 1) 为每一行设

我有这个
TextView
。它的一些部分应该向左对齐,一些部分应该向右对齐。在Java中如何实现这一点

基本上,我希望第一行向左对齐,下一行向右对齐,依此类推

有人有线索吗

编辑

我曾经尝试过使用HTML,但当它不起作用时,我尝试了使用spans

html尝试

textView.setText(Html.fromHtml("<p align=\"right\">THIS IS TO THE RIGHT</p>"));
但它们似乎都不起作用。

两种解决方案:

1) 为每一行设置不同的文本视图并设置其重力

2) 加载数据时使用Html为其设置Html对齐方式 这不起作用 编辑:


3:将使用span.

简单。在textview中调整xml部分。使用布局。如果您希望文本视图位于左侧

android:alignParentLeft=“true”有关align的更多详细信息,请参见此

这也是不同布局的一个例子

Alignment.ALIGN\u相反的是右侧的等效项。


Alignment.ALIGN\u NORMAL等同于left side。

这里有一个与Spannable一起工作的解决方案,如果右侧和左侧太宽,它们将在同一条线上重叠。由于使用spannable执行左/右技巧需要在左和右之间添加换行符,因此我的解决方案是添加一个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;
        }
    }
}

谢谢你的提示,@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

一个
SpannableStringBuilder
包装器,它的API不会让我觉得刺眼

  • 杰克·沃顿

启发了其他解决方案,但解决了多行文本问题和文本重叠问题

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库

嗯,我认为第二个使用HTML的解决方案是一个很好的方法,但它不起作用。。textView.setText(Html.fromHtml(“这应该在右边”);textView.setText(Html.fromHtml(“这应该在右边”);你确定html中的对齐方式也适用于textview吗?我刚刚尝试了一些示例,并研究了html不支持对齐方式是的,我也读了。。但为什么span解决方案不起作用。。这应该行得通,不是吗?嗯,它不对。textview中的重力重要吗?@user1991905
textview的重力在这里很重要。尽量不要在xml中提供
android:gravity
内部
TextView
。这只适用于我,如果我使用整行的span,而不是一部分:(@WonderCsabo
AlignmentSpan.Standard
是一种段落样式,因此您需要在
LeftText
(即.\n)中添加一个新行字符以使
RightText
右对齐。(我没有测试上面的特定示例)对于我来说,我只能让它与换行符“\n”一起使用而不是两个空格,并将setSpan的第二个参数设置为LeftText.length(),不带“+2”。我尝试了许多组合,试图消除我不想要的换行符,但没有找到令人满意的解决方案。这是一个很好的技巧,但如果在textview中LeftText超过1行(不带换行符),则不起作用
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
    }
}