1

我一直在寻找很多关于如何将 TextView 上的删除线效果设置为没有结果的动画。我在论坛和 StackOverflow 上得到的唯一东西是:

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

我想要做的是,像在 Play Store 上的待办事项应用程序中一样为删除线效​​果设置动画,例如 Any.do 将它放在从左到右滑动的项目上。

4

4 回答 4

3

你有几个选择:

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

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

如果您想了解动画本身的制作方法,您可以查看AnimatorAnimatorSet等及其相关指南

于 2013-10-23T06:42:24.830 回答
3

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

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();
}
于 2016-01-31T15:19:10.387 回答
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

}

于 2017-06-04T12:00:41.747 回答
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;
}
}
于 2017-10-26T02:46:25.117 回答