我需要实现文本行来显示从右到左的文本新闻。我使用了这个解决方案 - https://stackoverflow.com/a/8971920,并添加了一些消息堆栈和repeat times
功能。因此,我的项目中有java和xml部分(链接到Gist:https://gist.github.com/artseld/4aac2a3b75bb5a741216):
ScrollTextView.java
public class ScrollTextView extends TextView {
// scrolling feature
private Scroller mSlr;
// scroll speed
private float mScrollSpeed = 200f;
// the X offset when paused
private int mXPaused = 0;
// whether it's being paused
private boolean mPaused = true;
// messages
private LinkedList<Message> mMessages;
// current message
private String mMessage;
private int mRepeatTimes = 0;
/*
* constructor
*/
public ScrollTextView(Context context) {
this(context, null);
// customize the TextView
setSingleLine();
setEllipsize(null);
setVisibility(INVISIBLE);
}
/*
* constructor
*/
public ScrollTextView(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.textViewStyle);
// customize the TextView
setSingleLine();
setEllipsize(null);
setVisibility(INVISIBLE);
}
/*
* constructor
*/
public ScrollTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// customize the TextView
setSingleLine();
setEllipsize(null);
setVisibility(INVISIBLE);
}
/**
* add message to messages pool
* @param message String
* @param repeatTimes int
*/
public void addMessage(String message, int repeatTimes) {
if (mMessages == null) {
mMessages = new LinkedList<>();
}
mMessages.add(new Message(message, repeatTimes));
if (mMessage == null) {
mMessage = message;
mRepeatTimes = repeatTimes;
}
startScroll();
}
public void addMessage(String message) {
addMessage(message, 1);
}
/**
* begin to scroll the text from the original position
*/
public void startScroll() {
if (mMessage == null)
return;
// set text
if (getText() == null || !getText().equals(mMessage)) {
setVisibility(INVISIBLE);
setText(mMessage);
}
// 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;
// Do not know why it would not scroll sometimes
// if setHorizontallyScrolling is called in constructor.
setHorizontallyScrolling(true);
// use LinearInterpolator for steady scrolling
mSlr = new Scroller(this.getContext(), new LinearInterpolator());
setScroller(mSlr);
int scrollingLen = calculateScrollingLen();
int distance = scrollingLen - (getWidth() + mXPaused);
int duration = (int) (1000f * distance / mScrollSpeed);
setVisibility(VISIBLE);
mSlr.startScroll(mXPaused, 0, distance, 0, duration);
invalidate();
mPaused = false;
}
/**
* 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 = rect.width() + getWidth();
rect = null;
return scrollingLen;
}
/**
* pause scrolling the text
*/
public void pauseScroll() {
if (null == mSlr)
return;
if (mPaused)
return;
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();
}
@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) {
if (--mRepeatTimes > 0) {
startScroll();
return;
}
if (mMessages != null && !mMessages.isEmpty()) {
mMessage = mMessages.getFirst().getMessage();
mRepeatTimes = mMessages.getFirst().getRepeatTimes();
mMessages.removeFirst();
startScroll();
return;
}
mMessage = null;
mRepeatTimes = 0;
}
}
public float getScrollSpeed() {
return mScrollSpeed;
}
public void setScrollSpeed(float scrollSpeed) {
mScrollSpeed = scrollSpeed;
}
public boolean isPaused() {
return mPaused;
}
class Message {
private String mMessage;
private int mRepeatTimes = 1;
public Message(String message) {
mMessage = message;
}
public Message(String message, int repeatTimes) {
mMessage = message;
mRepeatTimes = repeatTimes;
}
public String getMessage() {
return mMessage;
}
public int getRepeatTimes() {
return mRepeatTimes;
}
}
}
MyActivity.java
public class MyActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
// ...
final ScrollTextView scrollText = (ScrollTextView) findViewById(R.id.scroll_text);
scrollText.addMessage("Message #1");
scrollText.addMessage("Message #2");
scrollText.addMessage("Message #3");
// ...
}
}
my_activity_layout.xml
<com.mydomain.myproject.ScrollTextView
android:id="@+id/scroll_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true" />
几乎所有工作都很好,但文本显示在textview的左侧几毫秒,然后才会按预期从右向左运行。
任何人都可以帮助我吗?非常感谢!