前言
繼承textview,并仿照源碼修改而來,主要是取消了焦點和選中了判斷,也不依賴文本的寬度。
聲明
歡迎轉載,但請保留文章原始出處:)
部落格園:http://www.cnblogs.com
農民伯伯: http://over140.cnblogs.com
正文
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLlR2bjlHcvN2LcNXZnFWbp9CXt92YuM3ZvxmYuNmLu9Wbt92Yvw1LcpDc0RHaiojIsJye.gif)
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:
case message_restart:
if (mstatus == marquee_running) {
if (mrepeatlimit >= 0) {
mrepeatlimit--;
}
start(mrepeatlimit);
}
}
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);
resetscroll();
private void resetscroll() {
mscroll = 0.0f;
void start(int repeatlimit) {
if (repeatlimit == 0) {
stop();
mrepeatlimit = repeatlimit;
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;
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;
}
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLlR2bjlHcvN2LcNXZnFWbp9CXt92YuM3ZvxmYuNmLu9Wbt92Yvw1LcpDc0RHaiojIsJye.gif)
代碼說明:
1、取消了焦點和選中的判斷
2、将延遲1200改為0,立即執行跑馬燈效果。
3、核心代碼都是直接從textview拷貝出來。
2014-04-25 更新
結束
這裡主要是提供一種解決問題的思路,實際使用還需要進行相應的修改。
轉載:http://www.cnblogs.com/over140/p/3164712.html