在TextView上制作透视动画

时间:2013-10-23 06:34:40

标签: android animation textview swipe strikethrough

我一直在搜索如何为TextView上的删除影响制作动画,但结果却没有。我在论坛和StackOverflow上得到的只有:

some_text_view.setPaintFlags(some_text_view.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG)

我想要做的是,像播放商店中的待办事项应用中的直播效果一样动画,例如Any.do在项目从左到右滑动。

4 个答案:

答案 0 :(得分:3)

您有几个选择:

  • 扩展TextView并创建一个自定义视图,用于检查STRIKE_THRU_TEXT_FLAG是否已设置并触发动画,该动画将在动画的每一帧上增加宽度的文本上绘制一条小线。

  • 使用空视图并将其放在TextView上(使用RelativeLayout,FrameLayout等)。确保此视图的尺寸与TextView完全匹配。然后按照与以前相同的策略为此视图设置动画:在视图的中心绘制一条水平线,其宽度在动画的每一帧处递增。

如果您想知道如何动画本身,那么您可以查看AnimatorAnimatorSet等及其related guides

答案 1 :(得分:3)

private fun TextView.startStrikeThroughAnimation(): ValueAnimator {
val span = SpannableString(text)
val strikeSpan = StrikethroughSpan()
val animator = ValueAnimator.ofInt(text.length)
animator.addUpdateListener {
    span.setSpan(strikeSpan, 0, it.animatedValue as Int, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
    text = span
    invalidate()
}
animator.start()
return animator

}

private fun TextView.reverseStrikeThroughAnimation(): ValueAnimator {
val span = SpannableString(text.toString())
val strikeSpan = StrikethroughSpan()
val animator = ValueAnimator.ofInt(text.length, 0)
animator.addUpdateListener {
    span.setSpan(strikeSpan, 0, it.animatedValue as Int, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
    text = span
    invalidate()
}
animator.start()
return animator

}

答案 2 :(得分:2)

我用这种方法制作了删除线动画:

private void animateStrikeThrough1(final TextView tv) {
    final int ANIM_DURATION = 1000;              //duration of animation in millis
    final int length = tv.getText().length();
    new CountDownTimer(ANIM_DURATION, ANIM_DURATION/length) {
        Spannable span = new SpannableString(tv.getText());
        StrikethroughSpan strikethroughSpan = new StrikethroughSpan();

        @Override
        public void onTick(long millisUntilFinished) {
            //calculate end position of strikethrough in textview
            int endPosition = (int) (((millisUntilFinished-ANIM_DURATION)*-1)/(ANIM_DURAT [ION/length));
            endPosition = endPosition > length ?
                    length : endPosition;
            span.setSpan(strikethroughSpan, 0, endPosition,
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            tv.setText(span);
        }

        @Override
        public void onFinish() {

        }
    }.start();
}

答案 3 :(得分:0)

// Created by kot32 on 2017/10/26.

public class AnimationText extends TextView {

private boolean isAnimationStarted;
private float targetLength;
private float totalLength;

private Paint strikePaint;
private float startY;

//should always show Strike-Through
private boolean isDeleted;

public AnimationText(Context context, AttributeSet attrs) {
    super(context, attrs);
    strikePaint = new Paint();
    strikePaint.setColor(Color.BLACK);
    strikePaint.setAntiAlias(true);
    strikePaint.setStyle(Paint.Style.FILL_AND_STROKE);
    strikePaint.setStrokeWidth(5);
}

public AnimationText(Context context) {
    super(context);
    strikePaint = new Paint();
    strikePaint.setColor(Color.BLACK);
    strikePaint.setAntiAlias(true);
    strikePaint.setStyle(Paint.Style.FILL_AND_STROKE);
    strikePaint.setStrokeWidth(5);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (isAnimationStarted) {
        //画线
        canvas.drawLine(0, startY, targetLength, startY, strikePaint);
    }
    if (isDeleted && !isAnimationStarted) {
        canvas.drawLine(0, startY, totalLength, startY, strikePaint);
    }
}

public void startStrikeThroughAnimation() {
    totalLength = getWidth();
    startY = (float) getHeight() / 2;
    isAnimationStarted = true;
    //利用动画逐渐画出一条删除线
    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, "targetLength", 0, totalLength);
    objectAnimator.setInterpolator(new AccelerateInterpolator());
    objectAnimator.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {

        }

        @Override
        public void onAnimationEnd(Animator animation) {
            isAnimationStarted = false;
        }

        @Override
        public void onAnimationCancel(Animator animation) {

        }

        @Override
        public void onAnimationRepeat(Animator animation) {

        }
    });
    objectAnimator.setDuration(300);
    objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            invalidate();
        }
    });
    objectAnimator.start();
    postInvalidate();
}

public void setDeleted(boolean deleted) {
    isDeleted = deleted;
    totalLength = getWidth();
}

public float getTargetLength() {
    return targetLength;
}

public void setTargetLength(float targetLength) {
    this.targetLength = targetLength;
}
}