【问题标题】:Android button text vertical scrollingAndroid按钮文字垂直滚动
【发布时间】:2015-12-22 14:22:17
【问题描述】:

我正在开发一个 android 应用程序,在一个屏幕上我有 10 个方形按钮。某些按钮上的文本太长而无法显示,因此目前仅显示一部分。我想要做的是让按钮的文本在按钮不在焦点时自动垂直滚动(在按钮内)。所以屏幕加载,文本无限滚动。每次到达结尾时,它都应该从文本的开头开始并再次向下滚动。我知道有一个选框属性,这可以水平实现,但我需要垂直。我研究了 scrollTo 方法,但它会立即滚动到底部。我会发布一些代码,但我所拥有的都是来自其他 SO 帖子。任何帮助将不胜感激!

【问题讨论】:

标签: android button scroll


【解决方案1】:

@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));

希望这对某人有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-02
    • 1970-01-01
    • 2021-06-06
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多