Last active
September 16, 2015 11:48
-
-
Save lsurvila/b46765bc85811f89de5e to your computer and use it in GitHub Desktop.
Fixes ellipsizing behaviour on certain cases when text has \n in it.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.ArrayList; | |
import java.util.List; | |
import android.content.Context; | |
import android.graphics.Canvas; | |
import android.text.Layout; | |
import android.text.Layout.Alignment; | |
import android.text.StaticLayout; | |
import android.text.TextUtils.TruncateAt; | |
import android.util.AttributeSet; | |
import android.widget.TextView; | |
/** | |
* Fixes ellipsizing behaviour on certain cases when text has \n in it. | |
* When view is drawn first will display ellipses with default Android ellipsize method after | |
* expanding/hiding will use this method. FIXME refactor to always use this method. | |
* Taken from http://stackoverflow.com/questions/2160619/android-ellipsize-multiline-textview | |
*/ | |
public class EllipsizingTextView extends TextView { | |
private static final String ELLIPSIS = "..."; | |
public interface EllipsizeListener { | |
void ellipsizeStateChanged(boolean ellipsized); | |
} | |
private final List<EllipsizeListener> ellipsizeListeners = new ArrayList<EllipsizeListener>(); | |
private boolean isEllipsized; | |
private boolean isStale; | |
private boolean programmaticChange; | |
private String fullText; | |
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); | |
} | |
public EllipsizingTextView(Context context, AttributeSet attrs, int defStyle) { | |
super(context, attrs, defStyle); | |
} | |
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; | |
} | |
@Override | |
public void setMaxLines(int maxLines) { | |
super.setMaxLines(maxLines); | |
this.maxLines = maxLines; | |
isStale = true; | |
} | |
public int getMaxLines() { | |
return maxLines; | |
} | |
@Override | |
public void setLineSpacing(float add, float mult) { | |
this.lineAdditionalVerticalPadding = add; | |
this.lineSpacingMultiplier = mult; | |
super.setLineSpacing(add, mult); | |
} | |
@Override | |
protected void onTextChanged(CharSequence text, int start, int before, int after) { | |
super.onTextChanged(text, start, before, after); | |
if (!programmaticChange) { | |
fullText = text.toString(); | |
isStale = true; | |
} | |
} | |
@Override | |
protected void onDraw(Canvas canvas) { | |
if (isStale) { | |
super.setEllipsize(null); | |
resetText(); | |
} | |
super.onDraw(canvas); | |
} | |
private void resetText() { | |
int maxLines = getMaxLines(); | |
String workingText = fullText; | |
boolean ellipsized = false; | |
if (maxLines != -1) { | |
Layout layout = createWorkingLayout(workingText); | |
if (layout.getLineCount() > maxLines) { | |
workingText = fullText.substring(0, layout.getLineEnd(maxLines - 1)).trim(); | |
while (createWorkingLayout(workingText + ELLIPSIS).getLineCount() > maxLines) { | |
int lastSpace = workingText.lastIndexOf(' '); | |
if (lastSpace == -1) { | |
break; | |
} | |
workingText = workingText.substring(0, lastSpace); | |
} | |
workingText = workingText + ELLIPSIS; | |
ellipsized = true; | |
} else { | |
// if it's not drawn yet will use default ellipsize method. | |
super.setEllipsize(TextUtils.TruncateAt.END); | |
} | |
} | |
if (!workingText.equals(getText())) { | |
programmaticChange = true; | |
try { | |
setText(workingText); | |
} finally { | |
programmaticChange = false; | |
} | |
} | |
isStale = false; | |
if (ellipsized != isEllipsized) { | |
isEllipsized = ellipsized; | |
for (EllipsizeListener listener : ellipsizeListeners) { | |
listener.ellipsizeStateChanged(ellipsized); | |
} | |
} | |
} | |
private Layout createWorkingLayout(String workingText) { | |
return new StaticLayout(workingText, getPaint(), getWidth() - getPaddingLeft() - getPaddingRight(), | |
Alignment.ALIGN_NORMAL, lineSpacingMultiplier, lineAdditionalVerticalPadding, false); | |
} | |
@Override | |
public void setEllipsize(TruncateAt where) { | |
// Ellipsize settings are not respected | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment