TextView maxLines,移动方法和ellipsize

avi*_*ran 9 android textview

我有一个TextViewmaxLines:5ellipsize:end应用,我还使用setMovementMethod(LinkMovementMethod.getInstance())TextView,使可点击的链接(HTML内容).

上述所有组合的组合禁用了被截断的文本和要追加的"..."后缀.

知道出了什么问题以及如何解决它?

如果不设置移动方法,一切都按预期工作.

关于赏金的更新:寻找除手动设置省略号之外的解决方案

Nil*_*hod 5

对不起,我迟到了这一点。

这是解决这个问题的小方法

主要活动

public class MainActivity extends AppCompatActivity {


    TextView htmlTextView;

    CustomEllipsizeTextView  customEllipsizeTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        htmlTextView = findViewById(R.id.htmlTextView1);

        customEllipsizeTextView = findViewById(R.id.customEllipsizeTextView);

        String value = "Hello this is a dummy textview";

        String myText = "You can visit my  Profile in <a href=\"/sf/users/536650971/?tab=profile\">stackoverflow</a> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis bibendum mattis risus eget pulvinar. Praesenttingd" +
                " commodo erat enim, id564654 congue sem tristique vitae. Proin vitae accumsan justo, ut imperdiet Mauris neque nibh, hendrerit id tortor vel, congue sagittis odio. Morbi elementum lobortis maximus. Etiam sit amet porttitor massa. Fusce sed magna quis arcu tincidunt finibus vitae id erat. " +
                "commodo erat enim, id54654 congue sem tristique vitae. Proin vitae accumsan commodo erat enim, id congue sem tristique vitae. Proin vitae accumsan Pellentesque massa mi, imperdiet eget accums ";


        SpannableString spanText2 = new SpannableString(myText);
        htmlTextView.setText(value);

        if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
            customEllipsizeTextView.setText(Html.fromHtml(spanText2.toString(), Html.FROM_HTML_MODE_LEGACY));
        } else {
            customEllipsizeTextView.setText(Html.fromHtml(spanText2.toString()));
        }

        htmlTextView.setMovementMethod(LinkMovementMethod.getInstance());
        customEllipsizeTextView.setMovementMethod(LinkMovementMethod.getInstance());
        customEllipsizeTextView.setOnTouchListener(new TouchTextView(spanText2));

    }

}
Run Code Online (Sandbox Code Playgroud)

layout.activity_main

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".FirstFragment">



    <TextView
        android:id="@+id/htmlTextView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:maxLines="1"
        android:text="@string/link_text" />

    <neel.com.demo.CustomEllipsizeTextView
        android:id="@+id/customEllipsizeTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ellipsize="end"
        android:linksClickable="true"
        android:maxLines="5"
        android:padding="5dp"
        android:visibility="visible" />


</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

自定义EllipsizeTextView

public class CustomEllipsizeTextView extends android.support.v7.widget.AppCompatTextView {
    public CustomEllipsizeTextView(Context context) {
        super(context);
    }

    public CustomEllipsizeTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomEllipsizeTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        StaticLayout layout = null;
        Field field = null;
        try {
            Field staticField = DynamicLayout.class.getDeclaredField("sStaticLayout");
            staticField.setAccessible(true);
            layout = (StaticLayout) staticField.get(DynamicLayout.class);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        if (layout != null) {
            try {
                field = StaticLayout.class.getDeclaredField("mMaximumVisibleLineCount");
                field.setAccessible(true);
                field.setInt(layout, getMaxLines());
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (layout != null && field != null) {
            try {
                field.setInt(layout, Integer.MAX_VALUE);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

触摸文本视图

public class TouchTextView implements View.OnTouchListener {
    Spannable spannable;

    public TouchTextView (Spannable spannable){
        this.spannable = spannable;
    }
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int action = event.getAction();
        if(!(v instanceof TextView)){
            return false;
        }
        TextView textView  = (TextView) v;
        if (action == MotionEvent.ACTION_UP ||
                action == MotionEvent.ACTION_DOWN) {
            int x = (int) event.getX();
            int y = (int) event.getY();

            x -= textView.getTotalPaddingLeft();
            y -= textView.getTotalPaddingTop();

            x += textView.getScrollX();
            y += textView.getScrollY();

            Layout layout = textView.getLayout();
            int line = layout.getLineForVertical(y);
            int off = layout.getOffsetForHorizontal(line, x);

            ClickableSpan[] link = spannable.getSpans(off, off, ClickableSpan.class);

            if (link.length != 0) {
                if (action == MotionEvent.ACTION_UP) {
                    link[0].onClick(textView);
                } else if (action == MotionEvent.ACTION_DOWN) {
                    Selection.setSelection(spannable,
                            spannable.getSpanStart(link[0]),
                            spannable.getSpanEnd(link[0]));
                }

                return true;
            } else {
                Selection.removeSelection(spannable);
            }
        }

        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

输出

在此处输入图片说明

这是解释:

我已经调试了 TextView 并发现了以下内容:

因此,当您使用 LinkMovementMethod() 时,实际上文本充当 Spannable。在其他情况下,它是字符串。

TextView 里面有以下一个条件

if (mText instanceof Spannable) {
//executes incase of LinkMovementMethod
            result = new DynamicLayout(mText, mTransformed, mTextPaint, wantWidth,
                    alignment, mTextDir, mSpacingMult, mSpacingAdd, mIncludePad,
                    mBreakStrategy, mHyphenationFrequency, mJustificationMode,
                    getKeyListener() == null ? effectiveEllipsize : null, ellipsisWidth);
        } else { 
   //executes without any movementmethod
..create StaticLayout
}
Run Code Online (Sandbox Code Playgroud)

所以 DynamicLayout 在内部调用 StaticLayout 来渲染文本,但是mMaximumVisibleLineCount当来自 DynamicLayout 时它没有在 StaticLayout 内部设置,所以它是 default Integer.MAX_VALUE。但是当从 String 创建 StaticLayout 时,它实际上设置mMaximumVisibleLineCountmaxLines. 这mMaximumVisibleLineCount用于显示椭圆大小。这就是为什么“...”没有显示的原因。

为了显示行数,以下代码有效

if (mMaxMode == LINES && mLayout.getLineCount() > mMaximum) {
            unpaddedHeight = Math.min(unpaddedHeight, mLayout.getLineTop(mMaximum));
        }
Run Code Online (Sandbox Code Playgroud)

mMaximum在这两种情况下都将设置为 maxLines,但mLayout.getLineCount()对于没有 MovementMethod 的情况将设置为 maxLines,对于有 MovementMethod 的情况,它将是原始字符串的行数


小智 0

  <TextView
        android:id="@+id/html"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:maxLines="5"
        android:ellipsize="end"/>

        //inside your activity
        public class A extends AppCompatActivity{

               TextView html = (TextView) view.findViewById(R.id.html);
               html.setText(Html.fromHtml("this is an example <a href=\"www.google.com\">google</a> link to google"));
               html.setMovementMethod(LinkMovementMethod.getInstance());
               .
               .
               .
         }
Run Code Online (Sandbox Code Playgroud)