ActionBar uses a transition to animate text changes. This transition
depends on testing the equality of start/end text values in CharSequence
objects. Without equals(), SpannableString will return false for objects
whose references are different, but whose text is exactly the same.
This CL adds the equals() method, and the accompanying hashcode method,
to ensure that two Spanned implementations will always be equal
if their text and span data are equal.
Issue #
10760075 Wrong unread count in actionbar
Change-Id: I5e77d40dd302eca035e8c56d40f3cd0aef8e6424
return mFilters;
}
+ // Same as SpannableStringInternal
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof Spanned &&
+ toString().equals(o.toString())) {
+ // Check span data
+ Object[] otherSpans = ((Spanned) o).getSpans(0,
+ ((Spanned) o).length(), Object.class);
+ if (mSpanCount == otherSpans.length) {
+ for (int i = 0; i < mSpanCount; ++i) {
+ Object thisSpan = mSpans[i];
+ Object otherSpan = otherSpans[i];
+ if (!thisSpan.equals(otherSpan) ||
+ getSpanStart(thisSpan) != getSpanStart(otherSpan) ||
+ getSpanEnd(thisSpan) != getSpanEnd(otherSpan) ||
+ getSpanFlags(thisSpan) != getSpanFlags(otherSpan)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ // Same as SpannableStringInternal
+ @Override
+ public int hashCode() {
+ int hash = toString().hashCode();
+ hash = hash * 31 + mSpanCount;
+ for (int i = 0; i < mSpanCount; ++i) {
+ Object span = mSpans[i];
+ hash = hash * 31 + span.hashCode();
+ hash = hash * 31 + getSpanStart(span);
+ hash = hash * 31 + getSpanEnd(span);
+ hash = hash * 31 + getSpanFlags(span);
+ }
+ return hash;
+ }
+
private static final InputFilter[] NO_FILTERS = new InputFilter[0];
private InputFilter[] mFilters = NO_FILTERS;
}
}
+ // Same as SpannableStringBuilder
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof Spanned &&
+ toString().equals(o.toString())) {
+ // Check span data
+ Object[] otherSpans = ((Spanned) o).getSpans(0,
+ ((Spanned) o).length(), Object.class);
+ if (mSpanCount == otherSpans.length) {
+ for (int i = 0; i < mSpanCount; ++i) {
+ Object thisSpan = mSpans[i];
+ Object otherSpan = otherSpans[i];
+ if (!thisSpan.equals(otherSpan) ||
+ getSpanStart(thisSpan) != getSpanStart(otherSpan) ||
+ getSpanEnd(thisSpan) != getSpanEnd(otherSpan) ||
+ getSpanFlags(thisSpan) != getSpanFlags(otherSpan)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ // Same as SpannableStringBuilder
+ @Override
+ public int hashCode() {
+ int hash = toString().hashCode();
+ hash = hash * 31 + mSpanCount;
+ for (int i = 0; i < mSpanCount; ++i) {
+ Object span = mSpans[i];
+ hash = hash * 31 + span.hashCode();
+ hash = hash * 31 + getSpanStart(span);
+ hash = hash * 31 + getSpanEnd(span);
+ hash = hash * 31 + getSpanFlags(span);
+ }
+ return hash;
+ }
+
private String mText;
private Object[] mSpans;
private int[] mSpanData;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.graphics.Color;
+import android.util.Log;
import android.view.ViewGroup;
import android.widget.TextView;
* @hide
*/
public class TextChange extends Transition {
+
+ private static final String LOG_TAG = "TextChange";
+
private static final String PROPNAME_TEXT = "android:textchange:text";
private static final String PROPNAME_TEXT_COLOR = "android:textchange:textColor";
}
};
addListener(transitionListener);
+ if (DBG) {
+ Log.d(LOG_TAG, "createAnimator returning " + anim);
+ }
return anim;
}
return null;