承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.cnhttp://www.bianceng.cn/OS/extra/
代码说明:
1、取消了焦点和选中的判断
2、将延迟1200改为0,立即执行跑马灯效果。
3、核心代码都是直接从TextView拷贝出来。
结束
这里主要是提供一种解决问题的思路,实际使用还需要进行相应的修改。
作者:cnblogs 农民伯伯
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android dx...
, android textview
, private
, textview
, final
, static
, float
, 动态textview
, marquee
, textview倾斜
, textview变色
, textview方法
, Android垂直跑马灯
TextView预渲染
textview跑马灯效果、textview跑马灯、textview跑马灯不会动、textview 跑马灯无效、安卓textview跑马灯,以便于您获取更多的相关知识。