package com.mediamonks.googleflip.ui.animation; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.support.v4.view.ViewCompat; import android.text.SpannableString; import android.text.Spanned; import android.text.TextPaint; import android.text.style.ReplacementSpan; import android.util.AttributeSet; import android.util.Log; import android.view.animation.AnimationUtils; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; /** * View class for large animated text */ public class LargeAnimatedTextView extends AbstractAnimatedTextview { private static final String TAG = LargeAnimatedTextView.class.getSimpleName(); private long _duration; private SpannableString _newText; private Interpolator _interpolator; public LargeAnimatedTextView(Context context) { super(context); } public LargeAnimatedTextView(Context context, AttributeSet attrs) { super(context, attrs); } public LargeAnimatedTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void initView() { _duration = 500; _interpolator = new DecelerateInterpolator(); } @Override public void setText(CharSequence text, BufferType type) { _newText = new SpannableString(text); TextChar[] letters = _newText.getSpans(0, _newText.length(), TextChar.class); for (TextChar letter : letters) { _newText.removeSpan(letter); } for (int i = 0; i < _newText.length(); i++) { _newText.setSpan(new TextChar(getTextSize()), i, i + 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); } super.setText(_newText, BufferType.SPANNABLE); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (_isAnimating) { if (_startTime == 0) { _startTime = AnimationUtils.currentAnimationTimeMillis(); } //Animate letters here long currentTime = AnimationUtils.currentAnimationTimeMillis(); long deltaTime = Math.min(currentTime - _startTime - _delay, _duration * _newText.length()); if(deltaTime >= 0) { TextChar[] letters = _newText.getSpans(0, _newText.length(), TextChar.class); final int length = letters.length; for (int i = 0; i < length; i++) { TextChar letter = letters[i]; float delta = (float) Math.max(Math.min((deltaTime - (i * (_duration / (length * 2)))), _duration), 0); delta = _interpolator.getInterpolation(delta / (float) _duration); letter.setAlpha(delta > 0 ? 1 : 0); letter.setScale(delta); letter.setDelta(delta); } } if (deltaTime < Math.min(3000, _duration * _newText.length())) { ViewCompat.postInvalidateOnAnimation(this); } else { onShowComplete(); } } } private class TextChar extends ReplacementSpan { private float _textSize; private float _alpha; private float _scale; private float _delta; private float _diffY; private float _endDiffY; public TextChar(float textSize) { _textSize = textSize; _scale = 1; } /** * @param value alpha [0-1] */ public void setAlpha(float value) { _alpha = Math.max(Math.min(value, 1.0f), 0.0f); } public void setScale(float value) { value = value + 0.4f; _scale = Math.max(Math.min(value, 1.0f), 0.2f); } public void setDelta(float value) { _delta = value; if (_delta < 0.5) { _diffY = ((-150 * (_delta + 0.5f)) + 100); _endDiffY = _diffY; } else if (_delta > 0.7) { _endDiffY = -50; float perc = (_delta - 0.7f) / 0.3f; _diffY = _endDiffY + 50 * perc; } } @Override public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { int size = (int) paint.measureText(text, start, end); // Log.d(TAG, "text: " + text + ", letter: " + text.charAt(start) + "size: " + size); return size; } @Override public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { paint.setAlpha((int) (_alpha * 255)); paint.setTextSize(_textSize * _scale); // Log.d(TAG, "CanvasHeight: " + canvas.getHeight()); canvas.drawText(text, start, end, x, y+_diffY, paint);// } @Override public void updateMeasureState(TextPaint ds) { ds.setTextSize(_textSize); } @Override public void updateDrawState(TextPaint ds) { ds.setTextSize(_textSize); } } }