package se.alexanderblom.delicious.view; import se.alexanderblom.delicious.R; import android.content.Context; import android.content.res.TypedArray; import android.text.SpannableStringBuilder; import android.text.TextPaint; import android.text.style.ForegroundColorSpan; import android.util.AttributeSet; import android.util.FloatMath; import android.util.TypedValue; import android.widget.TextView; public class ListTextView extends TextView { // Hard space private static final char SEPARATOR = '\u00a0'; private CharSequence text; private BufferType type; private String moreText; private int moreColor; public ListTextView(Context context) { this(context, null); } public ListTextView(Context context, AttributeSet attrs, int defStyle) { this(context, attrs); } public ListTextView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ListTextView); moreText = a.getString(R.styleable.ListTextView_moreText); if (moreText == null) { moreText = " + %d"; } moreColor = a.getColor(R.styleable.ListTextView_moreTextColor, 0); if (moreColor == 0) { TypedValue outValue = new TypedValue(); getContext().getTheme().resolveAttribute(android.R.attr.textColorTertiary, outValue, true); moreColor = getResources().getColor(outValue.resourceId); } a.recycle(); } @Override public void setText(CharSequence text, BufferType type) { super.setText(limitText(text), type); this.text = text; this.type = type; } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); CharSequence shortened = limitText(text); super.setText(shortened, type); } private CharSequence limitText(CharSequence text) { // Don't do any work if it fits or if we are zero width if (!tooLong(text) || getWidth() == 0) { return text; } SpannableStringBuilder builder = new SpannableStringBuilder(text); int numRemoved = 0; for (int i = builder.length() - 1; i >= 0; i--) { char c = builder.charAt(i); if (c == SEPARATOR) { builder.delete(i, builder.length()); numRemoved++; // Does it fit now? if (!tooLong(builder)) { String more = String.format(moreText, numRemoved); int moreLength = more.length() + 1; builder.append(' '); builder.append(more); builder.setSpan(new ForegroundColorSpan(moreColor), builder.length() - moreLength, builder.length(), 0); // Check if the more text actually fits if (!tooLong(builder)) { return builder; } } } } // Nothing seems to fit, we'll // just set the whole text then return text; } private boolean tooLong(CharSequence text) { TextPaint paint = getPaint(); float width = availableWidth(); return measure(paint, text) > width; } private int availableWidth() { return getWidth() - getPaddingLeft() - getPaddingRight(); } private int measure(TextPaint p, CharSequence text) { return (int) FloatMath.ceil(p.measureText(text, 0, text.length())); } }