具有 inter_word justificationMode 的可选 TextView

Selectable TextView with inter_word justificationMode

我正在尝试使用 justificationMode 使可选择的 TextView 合理化。 似乎这两个属性不能共存,因为当我从 TextView 中删除 android:textIsSelectable="true" 时,它就很好地证明了。 这是 TextView:

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fontFamily="@font/sf_reg"
        android:padding="16dp"
        android:textIsSelectable="true"
        android:justificationMode="inter_word"
        android:gravity="left|top"
        android:textColor="@android:color/black"
        android:textSize="15sp" />

我正在使用 androidx.appcompat:appcompat:1.1.0,targetSdkVersion 是 29,minSdkVersion 是 26。

Android 自 Oreo 以来仅支持 Textview 的完全对齐,尽管我们很难使用 justificationMode 对 textview 进行对齐。 但是您可以通过在 class.

中编写一个简单的方法来实现合理化
public void Justify(final TextView textView) {

        final AtomicBoolean isJustify = new AtomicBoolean(false);

        final String textString = textView.getText().toString();

        final TextPaint textPaint = textView.getPaint();

        final SpannableStringBuilder builder = new SpannableStringBuilder();

        textView.post(new Runnable() {
            @Override
            public void run() {

                if (!isJustify.get()) {

                    final int lineCount = textView.getLineCount();
                    final int textViewWidth = textView.getWidth();

                    for (int i = 0; i < lineCount; i++) {

                        int lineStart = textView.getLayout().getLineStart(i);
                        int lineEnd = textView.getLayout().getLineEnd(i);

                        String lineString = textString.substring(lineStart, lineEnd);

                        if (i == lineCount - 1) {
                            builder.append(new SpannableString(lineString));
                            break;
                        }

                        String trimSpaceText = lineString.trim();
                        String removeSpaceText = lineString.replaceAll(" ", "");

                        float removeSpaceWidth = textPaint.measureText(removeSpaceText);
                        float spaceCount = trimSpaceText.length() - removeSpaceText.length();

                        float eachSpaceWidth = (textViewWidth - removeSpaceWidth) / spaceCount;

                        SpannableString spannableString = new SpannableString(lineString);
                        for (int j = 0; j < trimSpaceText.length(); j++) {
                            char c = trimSpaceText.charAt(j);
                            if (c == ' ') {
                                Drawable drawable = new ColorDrawable(0x00ffffff);
                                drawable.setBounds(0, 0, (int) eachSpaceWidth, 0);
                                ImageSpan span = new ImageSpan(drawable);
                                spannableString.setSpan(span, j, j + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                            }
                        }

                        builder.append(spannableString);
                    }

                    textView.setText(builder);
                    isJustify.set(true);
                }
            }
        });
}

然后在方法中传递你的textview,

Textview tv = findviewbyid(R.id.text);
Justify(tv);

而且最棒的是,它不仅限于奥利奥,它也适用于其他较低版本的android。

android:textIsSelectable="true"

文本选择也适用于此方法。