I am using an alpha interpolation on a custom CharacterStyle
by setting an alpha value mAlpha
and then updating the color in updateDrawState(TextPaint tp)
.
I'm running into an issue on newer Android devices, specifically devices running API 23 don't seem to render the Spans
at all. On older devices the updates work properly.
Has anyone dealt with this issue?
Here is the code for the alpha being set inside onDraw
in a custom EditText
for some weird reason the characters sometimes do not show up on certain devices on other devices the animation works perfectly:
// If the view is animating (meaning we set the text) go ahead and draw the animations
if (mIsAnimating) {
long delta = AnimationUtils.currentAnimationTimeMillis() - mStart;
// Initialize our word span
FadeWordSpan[] words = mFadeText.getSpans(0, mFadeText.length(), FadeWordSpan.class);
// Get our length
final int length = words.length;
// For each letter animate in the word
for (int i = 0; i < length; i++) {
// Get our word
FadeWordSpan word = words[i];
long value = (delta - (i * mDurationPerWord));
// Calculate our delta
float dx = (float) Math.max(Math.min(value, mDurationPerWord), 0);
// Calculate the alpha based on the delta dx value
float alpha = mInterpolator.getInterpolation(dx / (float) mDurationPerWord);
// Set our interpolation alpha
word.setAlpha(alpha);
}
boolean keepRedrawing = delta < mDurationPerWord * length;
// If our delta is less than the duration per word times the length then we need to keep re-drawing
if (keepRedrawing) {
// Call redraw on animation change
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
postInvalidateOnAnimation();
} else
ViewCompat.postInvalidateOnAnimation(this);
// Else let our listener know we are done animating
} else {
// Go ahead and set our characters styles
FadeWordSpan[] letters = mFadeText.getSpans(0, mFadeText.length(), FadeWordSpan.class);
for (FadeWordSpan word : letters) {
mFadeText.removeSpan(word);
}
// Some animating
mIsAnimating = false;
// If our listener is not null go ahead and let the delegate know we have finished
// animating in the text
if (mAnimatingTextFinished != null) {
mAnimatingTextFinished.onFinished();
mAnimatingTextFinished = null;
}
}
}
UPDATE:
Devices that work are:
- Samsung S6
- HTC Devices
- Nexus 4
Devices that don't work are:
- Samsung S3
- Motorola Nexus 6
- Nexus 5
Update 2:
After debugging, it seems to be that updateDrawState(TextPaint tp)
never stops on the devices that don't work. Maybe it's blocking the part of the app that needs to render the text in.
Update 3:
StackTrace:
Update 4: Word Span Class
public class FadeWordSpan extends CharacterStyle implements UpdateAppearance {
private float mAlpha = 0.0f;
public FadeWordSpan() {
}
public void setAlpha(float alpha) {
this.mAlpha = Math.max(Math.min(alpha, 1.0f), 0.0f);
}
public float getAlpha() {
return mAlpha;
}
@Override
public void updateDrawState(TextPaint tp) {
// This constantly gets called on certain devices
Log.i(TAG, "updateDrawState: ");
int red = Color.red(Color.WHITE);
int green = Color.green(Color.WHITE);
int blue = Color.blue(Color.WHITE);
int alpha = Color.alpha(Color.WHITE);
int color = Color.argb((int) (alpha * mAlpha), red, green, blue);
tp.setColor(color);
}
}
Update 5:
Stack Dump (same as above, gets called infinitely):
W: java.lang.Throwable: stack dump
W: at java.lang.Thread.dumpStack(Thread.java:490)
W: at com.customapp.utils.views.text.FadeWordSpan.updateDrawState(FadeWordSpan.java:43)
W: at android.text.TextLine.handleRun(TextLine.java:953)
W: at android.text.TextLine.measureRun(TextLine.java:417)
W: at android.text.TextLine.measure(TextLine.java:296)
W: at android.text.TextLine.metrics(TextLine.java:270)
W: at android.text.BoringLayout.isBoring(BoringLayout.java:311)
W: at android.widget.TextView.onMeasure(TextView.java:6875)
W: at android.view.View.measure(View.java:18794)
W: at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715)
W: at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
W: at android.view.View.measure(View.java:18794)
W: at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715)
W: at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
W: at android.view.View.measure(View.java:18794)
W: at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
W: at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
W: at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
W: at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
W: at android.view.View.measure(View.java:18794)
W: at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
W: at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
W: at android.view.View.measure(View.java:18794)
W: at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
W: at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
W: at android.view.View.measure(View.java:18794)
W: at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715)
W: at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
W: at android.view.View.measure(View.java:18794)
W: at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
W: at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
W: at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:135)
W: at android.view.View.measure(View.java:18794)
W: at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
W: at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
W: at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
W: at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
W: at android.view.View.measure(View.java:18794)
W: at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
W: at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
W: at android.view.View.measure(View.java:18794)
W: at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
W: at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
W: at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
W: at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
W: at android.view.View.measure(View.java:18794)
W: at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
W: at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
W: at com.android.internal.policy.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2643)
W: at android.view.View.measure(View.java:18794)
W: at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2100)
W: at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1216)
W: at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1452)
W: at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
W: at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
W: at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
W: at android.view.Choreographer.doCallbacks(Choreographer.java:670)
W: at android.view.Choreographer.doFrame(Choreographer.java:606)
W: at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
W: at android.os.Handler.handleCallback(Handler.java:739)
W: at android.os.Handler.dispatchMessage(Handler.java:95)
W: at android.os.Looper.loop(Looper.java:148)
W: at android.app.ActivityThread.main(ActivityThread.java:5417)
W: at java.lang.reflect.Method.invoke(Native Method)
W: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
W: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)