You can extend TextView with overriding ellipsize behavior like I've done (based on code from this question: android ellipsize multiline textview)
import android.content.Context;
import android.graphics.Canvas;
import android.text.Layout;
import android.text.Layout.Alignment;
import android.text.SpannableStringBuilder;
import android.text.StaticLayout;
import android.text.TextUtils;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class EllipsizingTextView extends TextView {
private static final char ELLIPSIS = '…';
public interface EllipsizeListener {
void ellipsizeStateChanged(boolean ellipsized);
}
private final List<EllipsizeListener> ellipsizeListeners = new ArrayList<EllipsizeListener>();
private volatile boolean isEllipsized;
private volatile boolean isStale;
private volatile boolean programmaticChange;
private CharSequence fullCharSequence;
private int maxLines = -1;
private float lineSpacingMultiplier = 1.0f;
private float lineAdditionalVerticalPadding = 0.0f;
public EllipsizingTextView(Context context) {
super(context);
}
public EllipsizingTextView(Context context, AttributeSet attrs) {
super(context, attrs);
initAttributes(context, attrs);
}
public EllipsizingTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initAttributes(context, attrs);
}
private void initAttributes(Context context, AttributeSet attrs) {
maxLines = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "maxLines", -1);
if (maxLines != -1) {
isStale = true;
}
}
public void addEllipsizeListener(EllipsizeListener listener) {
if (listener == null) {
throw new NullPointerException();
}
ellipsizeListeners.add(listener);
}
public void removeEllipsizeListener(EllipsizeListener listener) {
ellipsizeListeners.remove(listener);
}
public boolean isEllipsized() {
return isEllipsized;
}
public void setMaxLines(int maxLines) {
if (getMaxLines() != maxLines) {
super.setMaxLines(maxLines);
this.maxLines = maxLines;
isStale = true;
}
}
public int getMaxLines() {
return maxLines;
}
public void setLineSpacing(float add, float mult) {
this.lineAdditionalVerticalPadding = add;
this.lineSpacingMultiplier = mult;
super.setLineSpacing(add, mult);
}
protected void onTextChanged(CharSequence text, int start, int before, int after) {
super.onTextChanged(text, start, before, after);
if (!programmaticChange) {
fullCharSequence = text;
isStale = true;
}
}
protected void onDraw(Canvas canvas) {
if (isStale) {
super.setEllipsize(null);
resetText();
}
super.onDraw(canvas);
}
private void resetText() {
int maxLines = getMaxLines();
boolean ellipsized = false;
SpannableStringBuilder builder = SpannableStringBuilder.valueOf(fullCharSequence);
if (maxLines != -1) {
Layout layout = createWorkingLayout(builder);
if (layout.getLineCount() > maxLines) {
int end = layout.getLineEnd(maxLines - 1);
int nextSpace = builder.toString().indexOf(' ', end);
if (nextSpace != -1) {
builder.delete(end, builder.length());
}
builder.append(ELLIPSIS);
while (createWorkingLayout(builder).getLineCount() > maxLines) {
int pos = builder.toString().lastIndexOf(' ');
builder.delete(pos, builder.length());
builder.append(ELLIPSIS);
}
ellipsized = true;
}
}
if (!TextUtils.equals(builder, getText())) {
programmaticChange = true;
try {
setText(builder);
} finally {
programmaticChange = false;
}
}
isStale = false;
if (ellipsized != isEllipsized) {
isEllipsized = ellipsized;
for (EllipsizeListener listener : ellipsizeListeners) {
listener.ellipsizeStateChanged(ellipsized);
}
}
}
private Layout createWorkingLayout(CharSequence workingText) {
return new StaticLayout(workingText, getPaint(), getWidth() - getPaddingLeft() - getPaddingRight(),
Alignment.ALIGN_NORMAL, lineSpacingMultiplier, lineAdditionalVerticalPadding, false);
}
public void setEllipsize(TruncateAt where) {
// Ellipsize settings are not respected
}
public int getLineCount() {
return Math.min(super.getLineCount(), getMaxLines());
}
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
if (changed) {
isStale = true;
}
super.onLayout(changed, left, top, right, bottom);
}
}
You can replace ELLIPSIS with your string (like "Show more") and add ForegroundColorSpan or BackgroundColorSpan for this part of text. Be careful with spaces in this case (it can lead you to infinite loop).