跑马灯效果

一句话概括,平移再画一次。

跑马灯效果_第1张图片




Textview 默认就支持跑马灯效果,但需要设置一些东西,满足一些条件。

但我想知道它的原理。

看这效果,就是平滑移动 Textview 的内容,这不就是 mScrollX 干的吗,结合 ValueAnimator 很容易就实现了。

难点在于,把文字的头部重新从右边开始画出来。


width 代表 Textview 的实际宽度。

lineWidth 代表文字宽度,比如 “ABCD” 的宽度。

gap 代表文字头部和尾部的间隙,默认为 width/3。

mGhostStart ,幽灵的起始位置?


当 Textview 平移了 mGhostStart 后,正好展示完 gap 的最后一像素。

在下一帧,就需要重新绘制文字头部了。

canvas.translate(mMaxScroll, 0.0f);
getLayout().draw(canvas, null, null, 0);


mMaxScroll = lineWidth + gap 

canvas 平移这段距离,就像是重新又从 A 开始绘画了。

知道原理后,用什么类实现都可以,改变 gap,改变速度,改变方向,垂直跑马灯等等。

canvas 真的是爹。


代码:

public class MyTextView extends TextView {

    public MyTextView(Context context) {
        super(context);
    }

    public MyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    //


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();
        if (isRunning() && shouldDrawGhost()) {
            // 平移重画
            canvas.translate(mMaxScroll, 0.0f);
            getLayout().draw(canvas, null, null, 0);
        }
        canvas.restore();
    }

    // 跑马中
    boolean running = false;

    public boolean isRunning() {
        return running;
    }

    // 该画幽灵部分了
    boolean shouldDrawGhost() {
        return isRunning() && getScrollX() > mGhostStart;
    }

    private float mMaxScroll;
    private float mGhostStart;

    public void start() {
        running = true;
        final int textWidth = getWidth();
        final float lineWidth = getLayout().getLineWidth(0);
        final float gap = textWidth / 3.0f;
        mGhostStart = lineWidth - textWidth + gap;
        mMaxScroll = lineWidth + gap;
        ValueAnimator animator = ValueAnimator.ofFloat(0, mMaxScroll);
        animator.setDuration(5000);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float f = (Float) animation.getAnimatedValue();
                setScrollX((int) f);
                if (1 == animation.getAnimatedFraction()) {
                    running = false;
                }
            }
        });
        animator.start();
    }

}






你可能感兴趣的:(跑马灯效果)