【Android】不依赖焦点和选中的TextView跑马灯

简介:

前言

继承TextView,并仿照源码修改而来,主要是取消了焦点和选中了判断,也不依赖文本的宽度。

 

声明
欢迎转载,但请保留文章原始出处:) 
博客园:http://www.cnblogs.com

农民伯伯: http://over140.cnblogs.com 

 

正文

复制代码
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;
        }
    }
}
复制代码

代码说明: 

1、取消了焦点和选中的判断

2、将延迟1200改为0,立即执行跑马灯效果。

3、核心代码都是直接从TextView拷贝出来。

 

2014-04-25 更新

强烈建议参考本文的最新版本:【Android】不依赖焦点和选中的TextView跑马灯【2】 

 

结束 

这里主要是提供一种解决问题的思路,实际使用还需要进行相应的修改。


转载:http://www.cnblogs.com/over140/p/3164712.html

目录
相关文章
|
6月前
|
XML Java Maven
Android线条等待动画JMWorkProgress(可添加依赖直接使用)
这是一篇关于Android线条等待动画JMWorkProgress的教程文章,作者计蒙将其代码开源至GitHub,提升可读性。文章介绍了如何通过添加依赖库使用该动画,并详细讲解了XML与Java中的配置方法,包括改变线条颜色、宽度、添加文字等自定义属性。项目已支持直接依赖集成(`implementation &#39;com.github.Yufseven:JMWorkProgress:v1.0&#39;`),开发者可以快速上手实现炫酷的等待动画效果。文末附有GitHub项目地址,欢迎访问并点赞支持!
204 26
|
6月前
|
Java Android开发
Android跑马灯的简单实现方式
本文介绍两种在Android中实现跑马灯效果的方法。第一种适用于从右至左滚动,要求字体长度超过控件长度,通过设置特定属性实现。第二种使用定时器调整padding值,实现更灵活的滚动方向。
356 19
|
6月前
|
XML 前端开发 Java
Android用Canvas画一个真正能跑的跑马灯
这是一篇关于使用Canvas实现跑马灯效果的技术分享。作者通过一个简单的Demo,展示了如何利用Android的Canvas绘制动态跑马灯。核心思路是通过开启耗时线程让彩色背景旋转,结合坐标计算、渐变色绘制和旋转动画,最终实现动态视觉效果。代码分为三个主要部分:1) 计算View宽高与矩形坐标;2) 绘制背景、跑马灯及幕布;3) 设置旋转逻辑并反向调整幕布。文末附有完整Java代码及XML调用示例,适合初学者学习Canvas绘图原理。
132 0
|
开发工具 Android开发 git
Android实战之组件化中如何进行版本控制和依赖管理
本文介绍了 Git Submodules 的功能及其在组件化开发中的应用。Submodules 允许将一个 Git 仓库作为另一个仓库的子目录,有助于保持模块独立、代码重用和版本控制。虽然存在一些缺点,如增加复杂性和初始化时间,但通过最佳实践可以有效利用其优势。
182 3
|
Android开发
Android经典实战之Textview文字设置不同颜色、下划线、加粗、超链接等效果
本文介绍了 `SpannableString` 在 Android 开发中的强大功能,包括如何在单个字符串中应用多种样式,如颜色、字体大小、风格等,并提供了详细代码示例,展示如何设置文本颜色、添加点击事件等,助你实现丰富文本效果。
1030 4
|
XML 存储 Java
浅谈Android的TextView控件
浅谈Android的TextView控件
127 0
|
XML IDE 开发工具
13. 【Android教程】文本框 TextView
13. 【Android教程】文本框 TextView
288 2
|
Android开发
android TextView HTML 的效果
android TextView HTML 的效果
94 2
|
编解码 Android开发
Android 解决TextView多行滑动与NestedScrollView嵌套滑动冲突的问题
Android 解决TextView多行滑动与NestedScrollView嵌套滑动冲突的问题
426 0
|
XML 搜索推荐 Java
Android TextView的字体设置
【5月更文挑战第13天】
963 0

热门文章

最新文章