本文章由azibug编写,转载请注明出处,请勿用于商业用途
文章链接:http://blog.youkuaiyun.com/owillll/article/details/8879896
作者:azibug 邮箱: azibug#163.com
原理:
1. 继承TextView并添加Scroller到TextView里面滚动条
2. 覆盖computeScroll方法并在Scroller滚动结束时重新开始滚动
3. TextView 的样式应该设置为单行和不需要ellipsize并且设置滚动为水平滚动
实例:
在layout中:
<com.chaokuaidi.android.util.ScrollTextView
android:ellipsize="marquee"
android:gravity="center"
android:id="@+id/textTitle"
android:layout_height="wrap_content"
android:scrollHorizontally="true"
android:singleLine="true"
android:marqueeRepeatLimit="marquee_forever"
android:layout_width="250px"/>
package com.chaokuaidi.android.util;
import android.content.Context;
import android.graphics.Rect;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.animation.LinearInterpolator;
import android.widget.Scroller;
import android.widget.TextView;
public class ScrollTextView extends TextView {
// scrolling feature
private Scroller mSlr;
// milliseconds for a round of scrolling
private int mRndDuration = 250;
// the X offset when paused
private int mXPaused = 0;
// whether it's being paused
private boolean mPaused = true;
/*
* constructor
*/
public ScrollTextView(Context context) {
this(context, null);
}
/*
* constructor
*/
public ScrollTextView(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.textViewStyle);
}
/*
* constructor
*/
public ScrollTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// customize the TextView
setSingleLine();
setEllipsize(null);
// setVisibility(INVISIBLE);
// use LinearInterpolator for steady scrolling
mSlr = new Scroller(this.getContext(), new LinearInterpolator());
// Do not know why it would not scroll sometimes
// if setHorizontallyScrolling is called in constructor.
setHorizontallyScrolling(true);
setScroller(mSlr);
}
/**
* calculate the scrolling length of the text in pixel
*
* @return the scrolling length in pixels
*/
private int calculateScrollingLen() {
TextPaint tp = getPaint();
Rect rect = new Rect();
String strTxt = getText().toString();
tp.getTextBounds(strTxt, 0, strTxt.length(), rect);
int scrollingLen = -1;
if (rect.width() > -10 + getWidth())
scrollingLen = rect.width() + getWidth();
rect = null;
return scrollingLen;
}
/**
* begin to scroll the text from the original position
*/
public void startScroll() {
// begin from the very right side
mXPaused = -1 * getWidth();
// assume it's paused
mPaused = true;
resumeScroll();
}
/**
* resume the scroll from the pausing point
*/
public void resumeScroll() {
if (!mPaused)
return;
int scrollingLen = calculateScrollingLen();
if (scrollingLen > 0) {
setGravity(3);
int distance = scrollingLen - (getWidth() + mXPaused);
int duration = (new Double(mRndDuration * distance * 1.00000
/ scrollingLen)).intValue();
// setVisibility(VISIBLE);
mSlr.startScroll(mXPaused, 0, distance, 0, duration);
mPaused = false;
} else {
reset();
}
}
/**
* pause scrolling the text
*/
public void pauseScroll() {
if (null == mSlr)
return;
if (!mPaused) {
mPaused = true;
// abortAnimation sets the current X to be the final X,
// and sets isFinished to be true
// so current position shall be saved
mXPaused = mSlr.getCurrX();
mSlr.abortAnimation();
}
}
public void reset() {
setGravity(17);
this.mXPaused = 0;
pauseScroll();
this.mPaused = true;
}
@Override
/*
* override the computeScroll to restart scrolling when finished so as that
* the text is scrolled forever
*/
public void computeScroll() {
super.computeScroll();
if (null == mSlr) return;
if (mSlr.isFinished() && (!mPaused)) {
this.startScroll();
}
}
public int getRndDuration() {
return mRndDuration;
}
public void setRndDuration(int duration) {
this.mRndDuration = duration;
}
public boolean isPaused() {
return mPaused;
}
}
可以根据某个宽度在不滚动是否显示文本而合理地取消setVisibility(INVISIBLE);的注释。
使用的时候很简单的两步:根据id初始化ScrollTextView控件并设置完整滚动完的时间,然后在适当的时候设置文本内容和开始滚动:
1.初始化
songName = (ScrollTextView)findViewById(R.id.textTitle);
songName.setRndDuration(15000); // 15秒
2. 设置内容和开始滚动:
songName.setText(title);
songName.startScroll();