Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android系統教程 >> Android開發教程 >> Android中不依賴焦點和選中的TextView跑馬燈

Android中不依賴焦點和選中的TextView跑馬燈

編輯:Android開發教程

承TextView,並仿照源碼修改而來,主要是取消了焦點和選中了判斷,也不依賴文本的寬度。

import java.lang.ref.WeakReference;
    
import android.content.Context;
import android.graphics.Canvas;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.widget.TextView;
    
public class MarqueeTextView extends TextView {
    
    private Marquee mMarquee;
    
    public MarqueeTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    public MarqueeTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    
    public MarqueeTextView(Context context) {
        super(context);
    }
    
    public void startMarquee() {
        startMarquee(-1);
    }
    
    public void startMarquee(int repeatLimit) {
        if (mMarquee == null)
            mMarquee = new Marquee(this);
        mMarquee.start(repeatLimit);
    }
    
    public void stopMarquee() {
        if (mMarquee != null && !mMarquee.isStopped()) {
            mMarquee.stop();
        }
    }
    
    public void toggleMarquee() {
        if (mMarquee == null || mMarquee.isStopped())
            startMarquee();
        else
            stopMarquee();
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        if (mMarquee != null && mMarquee.isRunning()) {
            final float dx = -mMarquee.getScroll();
            canvas.translate(getLayoutDirection() == LAYOUT_DIRECTION_RTL ? -dx
                    : +dx, 0.0f);
        }
        super.onDraw(canvas);
    }
    
    @SuppressWarnings("unused")
    private static final class Marquee extends Handler {
        // TODO: Add an option to configure this
        private static final float MARQUEE_DELTA_MAX = 0.07f;
        private static final int MARQUEE_DELAY = 0;// 1200;
        private static final int MARQUEE_RESTART_DELAY = 1200;
        private static final int MARQUEE_RESOLUTION = 1000 / 30;
        private static final int MARQUEE_PIXELS_PER_SECOND = 30;
    
        private static final byte MARQUEE_STOPPED = 0x0;
        private static final byte MARQUEE_STARTING = 0x1;
        private static final byte MARQUEE_RUNNING = 0x2;
    
        private static final int MESSAGE_START = 0x1;
        private static final int MESSAGE_TICK = 0x2;
        private static final int MESSAGE_RESTART = 0x3;
    
        private final WeakReference<TextView> mView;
    
        private byte mStatus = MARQUEE_STOPPED;
        private final float mScrollUnit;
        private float mMaxScroll;
        private float mMaxFadeScroll;
        private float mGhostStart;
        private float mGhostOffset;
        private float mFadeStop;
        private int mRepeatLimit;
    
        private float mScroll;
    
        Marquee(TextView v) {
            final float density = v.getContext().getResources()
                    .getDisplayMetrics().density;
            mScrollUnit = (MARQUEE_PIXELS_PER_SECOND * density)
                    / MARQUEE_RESOLUTION;
            mView = new WeakReference<TextView>(v);
        }
    
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MESSAGE_START:
                mStatus = MARQUEE_RUNNING;
                tick();
                break;
            case MESSAGE_TICK:
                tick();
                break;
            case MESSAGE_RESTART:
                if (mStatus == MARQUEE_RUNNING) {
                    if (mRepeatLimit >= 0) {
                        mRepeatLimit--;
                    }
                    start(mRepeatLimit);
                }
                break;
            }
        }
    
        void tick() {
            if (mStatus != MARQUEE_RUNNING) {
                return;
            }
    
            removeMessages(MESSAGE_TICK);
    
            final TextView textView = mView.get();
            // && (textView.isFocused() || textView.isSelected())
            if (textView != null) {
                mScroll += mScrollUnit;
                if (mScroll > mMaxScroll) {
                    mScroll = mMaxScroll;
                    sendEmptyMessageDelayed(MESSAGE_RESTART,
                            MARQUEE_RESTART_DELAY);
                } else {
                    sendEmptyMessageDelayed(MESSAGE_TICK, MARQUEE_RESOLUTION);
                }
                textView.invalidate();
            }
        }
    
        void stop() {
            mStatus = MARQUEE_STOPPED;
            removeMessages(MESSAGE_START);
            removeMessages(MESSAGE_RESTART);
            removeMessages(MESSAGE_TICK);
            resetScroll();
        }
    
        private void resetScroll() {
            mScroll = 0.0f;
            final TextView textView = mView.get();
            if (textView != null) {
                textView.invalidate();
            }
        }
    
        void start(int repeatLimit) {
            if (repeatLimit == 0) {
                stop();
                return;
            }
            mRepeatLimit = repeatLimit;
            final TextView textView = mView.get();
            if (textView != null && textView.getLayout() != null) {
                mStatus = MARQUEE_STARTING;
                mScroll = 0.0f;
                final int textWidth = textView.getWidth()
                        - textView.getCompoundPaddingLeft()
                        - textView.getCompoundPaddingRight();
                final float lineWidth = textView.getLayout().getLineWidth(0);
                final float gap = textWidth / 3.0f;
                mGhostStart = lineWidth - textWidth + gap;
                mMaxScroll = mGhostStart + textWidth;
                mGhostOffset = lineWidth + gap;
                mFadeStop = lineWidth + textWidth / 6.0f;
                mMaxFadeScroll = mGhostStart + lineWidth + lineWidth;
    
                textView.invalidate();
                sendEmptyMessageDelayed(MESSAGE_START, MARQUEE_DELAY);
            }
        }
    
        float getGhostOffset() {
            return mGhostOffset;
        }
    
        float getScroll() {
            return mScroll;
        }
    
        float getMaxFadeScroll() {
            return mMaxFadeScroll;
        }
    
        boolean shouldDrawLeftFade() {
            return mScroll <= mFadeStop;
        }
    
        boolean shouldDrawGhost() {
            return mStatus == MARQUEE_RUNNING && mScroll > mGhostStart;
        }
    
        boolean isRunning() {
            return mStatus == MARQUEE_RUNNING;
        }
    
        boolean isStopped() {
            return mStatus == MARQUEE_STOPPED;
        }
    }
}

查看本欄目更多精彩內容:http://www.bianceng.cn/OS/extra/

代碼說明:

1、取消了焦點和選中的判斷

2、將延遲1200改為0,立即執行跑馬燈效果。

3、核心代碼都是直接從TextView拷貝出來。

結束

這裡主要是提供一種解決問題的思路,實際使用還需要進行相應的修改。

作者:cnblogs 農民伯伯

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved