我正在开发一个Android应用程序,在一个屏幕上我有10个方形按钮。某些按钮上的文字太长而无法显示,所以目前只有一部分按钮显示。我想要做的是按钮'当按钮未对焦时,文本会自动垂直滚动(在按钮内)。因此屏幕加载并且文本无限滚动。每当它到达结尾时,它应该从文本的开头开始并再次向下滚动。我知道有一个marquee属性,这可以水平实现,但我需要它垂直。我研究了scrollTo方法,但它立即滚动到底部。我会发布一些代码,但无论我有什么来自其他SO帖子。任何帮助将不胜感激!
答案 0 :(得分:0)
@brokenstar提供了一个真正帮助我的链接。我必须做一些修改才能满足我的特定需求,所以这里是修改后的代码。
public class SquareButtonVScrolling extends SquareButton {
private boolean stop;
private boolean isNotDrawn = true;
private final Activity activity;
private long duration;
private int pixelYOffSet;
public SquareButtonVScrolling(Context context, AttributeSet attrs) {
super(context, attrs);
this.activity = (Activity) context;
}
public SquareButtonVScrolling(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.activity = (Activity) context;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = View.MeasureSpec.getSize(widthMeasureSpec);
setMeasuredDimension(width, width);
}
public void init() {
// If there are more lines than can be displayed startMarquee, otherwise don't do anything
if ((SquareButtonVScrolling.this).getLineCount() > (SquareButtonVScrolling.this).getHeight() / (SquareButtonVScrolling.this).getLineHeight()) {
setDuration(65l);
setPixelYOffSet(1);
stop = false;
startMarquee();
}
}
/**
* @return Returns the (long) duration in milliseconds between calls to the
* next scrollBy(0, pixelYOffSet).
*/
public long getDuration() {
return duration;
}
/**
* @param duration
* Sets the (long) duration in milliseconds between calls to the
* next scrollBy(0, pixelYOffSet). Defaults to 65L if value is
* less than or equal to 0.
*/
public void setDuration(long duration) {
if (duration <= 0) {
this.duration = 65l;
} else {
this.duration = duration;
}
}
/**
* @return Returns the (int) amount of Y pixels to scroll by.
*/
public int getPixelYOffSet() {
return pixelYOffSet;
}
/**
* @param pixelYOffSet
* Sets the (int) amount of Y pixels to scroll by. Defaults to 1
* if value is less.
*/
public void setPixelYOffSet(int pixelYOffSet) {
if (pixelYOffSet < 1) {
this.pixelYOffSet = 1;
} else {
this.pixelYOffSet = pixelYOffSet;
}
}
/**
* Starts the marquee
*/
private void startMarquee() {
new AutoScrollSquareButton().executeOnExecutor(Utils.CUSTOM_THREAD_POOL_EXECUTOR);
}
/**
* Stop the marquee.
*/
public void stopMarquee() {
stop = true;
}
private class AutoScrollSquareButton extends AsyncTask<Void, Void, Void> {
private int pixelCount;
@Override
protected Void doInBackground(Void... params) {
// Check to see if the VMSB has been drawn to get proper sizing.
while (squareButtonNotDrawn()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while (!stop) {
// Sleep duration amount between scrollBy pixelYOffSet
try {
Thread.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
// if VMSB has reached or exceeded the last
// Y pixel scroll back to top
if ((SquareButtonVScrolling.this).getScrollY() >= pixelCount) {
(SquareButtonVScrolling.this).scrollTo(0, 0);
} else { // Otherwise scroll by the pixelYOffSet
(SquareButtonVScrolling.this).scrollBy(0, pixelYOffSet);
}
(SquareButtonVScrolling.this).invalidate();
}
});
}
return null;
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
private boolean squareButtonNotDrawn() {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
// Checks to see if VMSB has been drawn.
if ((SquareButtonVScrolling.this).isShown()) {
// Calculate the total pixel height that needs to be scrolled.
// May need additional calculations if there is additional padding.
pixelCount = (SquareButtonVScrolling.this).getLineHeight() * (SquareButtonVScrolling.this).getLineCount();
isNotDrawn = false;
}
}
});
return isNotDrawn;
}
}
}
调用init()函数时,需要确保getLineCount(),getHeight()和getLineHeight()将返回所需的值而不是0.这些函数需要在绘制视图后调用我的情况我这样调用了init():
myView.postDelayed(new Runnable() {
@Override
public void run() {
myView.init();
}
}, 20);
20ms的小延迟就足够了。此外,因为我有多达30个垂直自动滚动按钮,我需要使用executeOnExecutor来启动带有自定义线程池的AsyncTask(为了让多个按钮同时滚动)。这是我使用的定义:
/**
* A custom {@link Executor} that can be used to execute tasks in parallel.
*/
public static final Executor CUSTOM_THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(30, 30, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(128));
希望这有助于某人!