【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】
结束
这里主要是提供一种解决问题的思路,实际使用还需要进行相应的修改。
【Android】不依赖焦点和选中的TextView跑马灯的更多相关文章
- 【Android】不依赖焦点和选中的TextView跑马灯【2】
前言 之前有写一篇TextView跑马灯的效果,后来实际项目中有发现新的问题,比如还是无法自动跑,文本超过了显示区域就截取的问题,今天换了一种思路来实现,更简单更好用. 声明 欢迎转载,但请保留文章原 ...
- [Android1.5]TextView跑马灯效果
from: http://www.cnblogs.com/over140/archive/2010/08/20/1804770.html 前言 这个效果在两周前搜索过,网上倒是有转载,可恨的是转载之后 ...
- Android:TextView跑马灯-详解
Android:TextView跑马灯_详解 引言: TextView之所以需要跑马灯,是由于文字太长,或者是吸引眼球. 关键代码如下: android:singleLine="true&q ...
- 【Android】TextView跑马灯效果
老规矩,先上图看效果. 说明 TextView的跑马灯效果也就是指当你只想让TextView单行显示,可是文本内容却又超过一行时,自动从左往右慢慢滑动显示的效果就叫跑马灯效果. 其实,TextView ...
- TextView 跑马灯
首先,写一个类,让其继承自TextView: 重写focus方法,让TextView始终是focus. public class MarqueeText extends TextView { publ ...
- TextView跑马灯
TextView跑马灯 textView跑马灯实现:1.定义textView标签的4个属性:android:singleLine="true"//使其只能单行android:ell ...
- Third Day:正式编程第三天,学习实践内容TextView跑马灯、AutoCompleteTextView、multiAutoCompleteTextView以及ToggleButton、checkedBox、RadioButton等相关实践
2.针对Focused的TextView跑马灯(文字较多一行无法显示)效果 针对单个TextView的跑马灯效果,可直接在TextView控件参数中添加三个属性: android:singleLine ...
- android textview 跑马灯
<TextView android:layout_width="match_parent" android:layout_height="48dp" an ...
- Android学习总结——TextView跑马灯效果
Android系统中TextView实现跑马灯效果,必须具备以下几个条件: 1.android:ellipsize="marquee" 2.TextView必须单行显示,即内容必须 ...
随机推荐
- 用redux构建购物车
很久没更新博客了,最近要用到react,再来跟大家分享一个redux案例吧. [ {"id": 1, "title": "iPad 4 Mini&qu ...
- Hive SQL 监控系统 - Hive Falcon
1.概述 在开发工作当中,提交 Hadoop 任务,任务的运行详情,这是我们所关心的,当业务并不复杂的时候,我们可以使用 Hadoop 提供的命令工具去管理 YARN 中的任务.在编写 Hive SQ ...
- Android Studio快捷键每日一练(4)
原文地址:http://www.developerphil.com/android-studio-tips-of-the-day-roundup-4/ 33.分析数据流到当前位置 苹果/Windows ...
- JSONP实现跨域
首先提出:什么是跨域?如何解决跨域? 跨域可以简单的理解为从一个域名访问另一个域名,由于javascript的同源政策的限制,出于安全的考虑,不允许浏览器这么做.比如a.com 域名下的js无法操作b ...
- 近期总结:generator-web,前端自动化构建的解决方案
本文结合最近的工作经验,总结出一个较简洁的前端自动化构建方案,主张css和js的模块化,并通过grunt的自动化构建,有效地解决css合并,js合并和图片优化等问题,对于提高前端性能和项目代码质量有一 ...
- js实现数组的排序和分组
问题: data=[1,1,1,1,2,2,2,2,5,5,5,8,8,8,2,2,2,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4] 怎么把值为1,2,3,4,5,8的数据分成 ...
- Android 手机上获取物理唯一标识码[转]
所有添加有谷歌账户的设备可以返回一个 ANDROID_ID 所有的CDMA设备对于 ANDROID_ID 和 TelephonyManager.getDeviceId() 返回相同的值(只要在设置时添 ...
- ASP.NET MVC程序播放H.264视频
在这篇之前,Insus.NET不管是在ASP.NET还是ASP.NET MVC实现很多视频播放,你可以参考这篇链接:http://www.cnblogs.com/insus/category/4650 ...
- Swift注释
Swift 中的普通注释与 Objective-C 中的一致,大概分为以下三种 // 单行注释 何问起 / * 多行注释 hovertree.com */ /// 标记注释1 http://hove ...
- ASP.NET MVC 模块与组件(二)——定制图片验证码
本着简洁直接,我们就直奔主题吧! 下面是一个生成数字和字母随机组合的验证码类源代码: using System; using System.Drawing; using System.Drawing ...