Sorry I'm late on this one.
Here is little work around for this
MainActivity
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=\"https://stackoverflow.com/users/7666442/nilesh-rathod?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));
}
}
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>
CustomEllipsizeTextView
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();
}
}
}
}
TouchTextView
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;
}
}
OUTPUT

Here is the explanation :
I have debugged TextView and found out the following :
So when you use LinkMovementMethod() actually text is acting as Spannable. In other case it is String.
There is one following condition inside 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
}
So DynamicLayout internally calls StaticLayout to render text, but it is not setting mMaximumVisibleLineCount
inside StaticLayout when coming from DynamicLayout so it is default Integer.MAX_VALUE
. But when creating StaticLayout from String, it is actually setting mMaximumVisibleLineCount
as maxLines
. This mMaximumVisibleLineCount
is used for displaying ellipsize. That's why "..." is not displaying.
For displaying the number of lines, the following code works
if (mMaxMode == LINES && mLayout.getLineCount() > mMaximum) {
unpaddedHeight = Math.min(unpaddedHeight, mLayout.getLineTop(mMaximum));
}
mMaximum
will be set to maxLines in both case, but mLayout.getLineCount()
will be maxLines for one without MovementMethod and for with MovementMethod it will be number of lines of original string