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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14520808/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 16:31:39  来源:igfitidea点击:

Make a certain part of a android-textview align to the right

javaandroidandroid-widget

提问by user1991905

I have this TextView. Some parts of it is supposed to be aligned to the left and some parts to the right. How would I do this in Java?

我有这个TextView。它的某些部分应该与左侧对齐,而某些部分应该与右侧对齐。我将如何在 Java 中做到这一点?

Basicly I want the first line to align to the left, and the next line to the right and so on.

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

Anyone got a clue?

有人有线索吗?

EDIT

编辑

I have tried to use HTML and then when that did not work I tried spans.

我曾尝试使用 HTML,然后当它不起作用时,我尝试了跨度。

html attempt

html 尝试

textView.setText(Html.fromHtml("<p align=\"right\">THIS IS TO THE RIGHT</p>"));

And heres the span attempt

这是跨度尝试

    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);

But none of them seems to work.

但它们似乎都不起作用。

回答by Vikalp Patel

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_OPPOSITE is the equivalent for right side.

Alignment.ALIGN_NORMAL is the equivalent for left side.

Alignment.ALIGN_NORMAL is the equivalent for left side.

回答by Frank

Here is a solution that works with Spannable, with the cavate that if the right and left are too wide, they will overlap on the same line. Since to do the Left/Right trick with a spannable requires a line feed between Left and Right, my fix is to add a spannable that reduces the line height to zero (i.e. overlapped lines) for the one linefeed and then restore normal line height after that.

这是一个适用于 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);

And we have the small routine to handle the overlapping lines:

我们有一个小程序来处理重叠的线:

    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;
        }
    }
}

回答by Eugen Pechanec

Thanks for the tip, @Frank, but this was just enough:

感谢您的提示,@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;
    }
}

Used like this:

像这样使用:

CharSequence text = return new Truss()
        .append("LEFT")
        .pushSpan(LineOverlapSpan())
        .append("\n")
        .popSpan()
        .pushSpan(AlignmentSpan.Standard(Layout.Alignment.ALIGN_OPPOSITE))
        .append("RIGHT")
        .build()

where Trussis

这里Truss

A SpannableStringBuilderwrapper whose API doesn't make me want to stab my eyes out.

一个SpannableStringBuilder包装器,它的 API 不会让我想刺伤我的眼睛。

回答by Nimish Choudhary

Two solution :

两种解决方案:

1) have a different text view for each line and set its gravity.

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

2) Use Html while loading data setting the alignment in html for it REF:how-to-display-html-in-textviewThis will not workalign is not a supported tagsEdited:

2) 在加载数据时使用 Html 为其设置 html 中的对齐方式 REF:how-to-display-html-in-textview这将不起作用align is not a supported tagsEdited:

Also

3: will be to use a span.

3:将使用跨度。

回答by Shadow

Simple.Adjust xml part in textview. Use layouts.If you want the textview to be in left

文本视图中的 Simple.Adjust xml 部分。使用布局。如果您希望文本视图位于左侧

android:alignParentLeft="true" For more align details look this.

android:alignParentLeft="true" 更多对齐细节请看这里。

http://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams.html

http://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams.html

And this is also an example for different layouts.

这也是不同布局的示例。

http://www.androidhive.info/2011/07/android-layouts-linear-layout-relative-layout-and-table-layout/

http://www.androidhive.info/2011/07/android-layouts-linear-layout-relative-layout-and-table-layout/

回答by frogggias

Inspired other solutions, but resolving multiline text issues and text overlap issue.

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

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
        }
    }

}

Usage:

用法:

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 solution is using Kpan library https://github.com/2dxgujun/Kpan

Kotlin 解决方案是使用 Kpan 库https://github.com/2dxgujun/Kpan