Android View 跑马灯效果

TextView 跑马灯效果 文字内容长度大于控件自身宽度时候,开启跑马灯效果
public class AutoPollTextView extends View {

    private int textColor;
    private int textSize;
    private Rect rect;
    private TextPaint paint;
    private String contentStr = "";
    private String showContentStr = "";
    private Marquee mMarquee;
    private float textHeight;
    private int textWidth;


    public void setText(String text, String tag) {
        if (tag != null && !tag.equals(getTag())) {
            text = text == null ? "" : text;
            if (!contentStr.equals(text)) {
                contentStr = text;
            }
            invalidate();
        }

    }


    public static final class Marquee {
        private static final int MARQUEE_DELAY = 0;
        private static final byte MARQUEE_STOPPED = 0x0;
        private static final byte MARQUEE_STARTING = 0x1;
        private static final byte MARQUEE_RUNNING = 0x2;

        private final WeakReference<AutoPollTextView> mView;
        private final Choreographer mChoreographer;

        private byte mStatus = MARQUEE_STOPPED;
        private final float mPixelsPerMs = 1f;
        private float mMaxScroll;
        private float mGhostStart;
        private float mScroll;
        private String blackStr = "";

        public Marquee(AutoPollTextView view) {
            this.mView = new WeakReference<>(view);
            mChoreographer = Choreographer.getInstance();

        }

        private Choreographer.FrameCallback mTickCallback = new Choreographer.FrameCallback() {
            @Override
            public void doFrame(long frameTimeNanos) {
                tick();
            }
        };

        private Choreographer.FrameCallback mStartCallback = new Choreographer.FrameCallback() {
            @Override
            public void doFrame(long frameTimeNanos) {
                mStatus = MARQUEE_RUNNING;
                tick();
            }
        };

        private Choreographer.FrameCallback mRestartCallback = new Choreographer.FrameCallback() {
            @Override
            public void doFrame(long frameTimeNanos) {
                if (mStatus == MARQUEE_RUNNING) {
                    start();
                }
            }
        };

        void tick() {
            if (mStatus != MARQUEE_RUNNING) {
                return;
            }

            mChoreographer.removeFrameCallback(mTickCallback);

            final AutoPollTextView textView = mView.get();
            if (textView != null) {
                float deltaPx = mPixelsPerMs * 1;
                mScroll += deltaPx;
                if (mScroll > mMaxScroll) {
                    mScroll = 0.0f;
                    mChoreographer.postFrameCallbackDelayed(mRestartCallback, MARQUEE_DELAY);
                } else {
                    mChoreographer.postFrameCallback(mTickCallback);
                }
                textView.invalidate();
            }
        }

        void stop() {
            mStatus = MARQUEE_STOPPED;
            mChoreographer.removeFrameCallback(mStartCallback);
            mChoreographer.removeFrameCallback(mRestartCallback);
            mChoreographer.removeFrameCallback(mTickCallback);
        }

        void start() {
            final AutoPollTextView textView = mView.get();
            if (textView != null) {
                mStatus = MARQUEE_STARTING;
//                mScroll = 0.0f;
                final int textWidth = textView.getWidth();
                final float lineWidth = textView.textWidth();
                final float gap = textWidth / 3.0f;
                mGhostStart = lineWidth - textWidth + gap;
                mMaxScroll = mGhostStart + textWidth;
                textView.invalidate();
                mChoreographer.postFrameCallback(mStartCallback);
            }
        }

        public String textWidthStr() {
            String textBlackStr = "";
            if (mView != null) {
                final AutoPollTextView textView = mView.get();
                if (textView != null) {
                    float l = textView.getWidth() / 3f;
                    float c = textView.contentWidthHeight();
                    int f = (int) ((int) l / c);
                    for (int w = 0; w < f; w++) {
                        textBlackStr = textBlackStr + " ";
                    }
                }
            }
            return textBlackStr;
        }

        String getBlackStr() {
            if (blackStr != null && blackStr.length() > 0) {
                return blackStr;
            }
            blackStr = textWidthStr();
            return blackStr;
        }

        float getScroll() {
            return mScroll;
        }

        boolean isRunning() {
            return mStatus == MARQUEE_RUNNING;
        }

        boolean isStopped() {
            return mStatus == MARQUEE_STOPPED;
        }


    }


    public AutoPollTextView(Context context) {
        this(context, null);
    }

    public AutoPollTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AutoPollTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AutoPollTextView);
        textColor = a.getColor(R.styleable.AutoPollTextView_ap_text_color, Color.parseColor("#f21646"));
        textSize = a.getDimensionPixelOffset(R.styleable.AutoPollTextView_ap_text_size, dp2px(12));
        a.recycle();

        rect = new Rect();
        paint = new TextPaint(Paint.ANTI_ALIAS_FLAG);//初始化文本画笔
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(textColor);//文字颜色值,可以不设定
        paint.setTextSize(textSize);//文字大小
        mMarquee = new Marquee(this);
    }


    @Override
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        super.onWindowFocusChanged(hasWindowFocus);
        startStopMarquee(hasWindowFocus);

    }


    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
        startStopMarquee(visibility == View.VISIBLE);
    }

    private void startStopMarquee(boolean start) {
        if (start) {
            startMarquee();
        } else {
            stopMarquee();
        }
    }

    private void stopMarquee() {
        if (mMarquee != null && !mMarquee.isStopped()) {
            mMarquee.stop();
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        restartMarqueeIfNeeded();
        super.onDraw(canvas);

        if (compressText(getWidth()) && mMarquee != null) {
            if (!showContentStr.equals(contentStr)) {
                showContentStr = contentStr + mMarquee.getBlackStr() + contentStr;
            }
            canvas.drawText(showContentStr, -mMarquee.getScroll(), getHeight() / 2 + textHeight / 2, paint);
        } else {
            canvas.drawText(contentStr, (getWidth() - textWidth) / 2, getHeight() / 2 + textHeight / 2, paint);
        }

    }

    private void restartMarqueeIfNeeded() {
        startMarquee();
    }


    private void startMarquee() {
        // Do not ellipsize EditText
        if (!compressText(getWidth())) {
            return;
        }

        if (mMarquee == null) mMarquee = new Marquee(this);

        if (!mMarquee.isRunning()) {
            mMarquee.start();
        }
    }


    public boolean compressText(float width) {
        if (rect == null) {
            rect = new Rect();
        }
        paint.getTextBounds(contentStr, 0, contentStr.length(), rect);
        textHeight = getContentHeight();
        textWidth = rect.width();
        return rect.width() > width;
    }

    public float textWidth() {
        return textWidth;
    }

    private float getContentHeight() {
        if (paint != null) {
            Paint.FontMetrics fontMetrics = paint.getFontMetrics();
            return Math.abs((fontMetrics.bottom - fontMetrics.top)) / 2;
        }
        return dp2px(30);
    }


    private float contentWidthHeight() {
        String text1 = "en en";
        String text2 = "enen";
        return contentWidth(text1) - contentWidth(text2);
    }

    private float contentWidth(String black) {
        if (black == null || black == "") {
            return 0;
        }
        if (rect == null) {
            rect = new Rect();
        }
        paint.getTextBounds(black, 0, black.length(), rect);
        textHeight = getContentHeight();
        return rect.width();
    }

    public int dp2px(float dpValue) {
        final float scale = getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值