使视图一一可见; android

Make views visible one by one; android

我在使视图可见时遇到了问题。如:它们确实全部出现,但同时出现,而我想在它们之间有一些延迟来显示它们。目前我有以下代码,应该更清楚:

public void performExperiment (View v) {
    Log.i(TAG, "Experiment has started on view: " + v);
    final ArrayList<FocusPoint> permutation = new ArrayList<>(Arrays.asList(focusPoints));
    Collections.shuffle(permutation);

    for (FocusPoint fp: permutation) {
        try {
            Thread.sleep(1000);
            fp.setVisibility(ImageView.VISIBLE);
            //fp.invalidate();
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "Sleep failed");
        }
    }
}

FocusPoint-class 是 Android 中 ImageView 的扩展,单击按钮时会调用该方法。

需要做的是所有视图都以随机顺序显示在屏幕上,它们之间有一秒钟。然而,此代码等待 16 秒(视图数量为 16),然后一次显示所有视图。我尝试使我的视图无效以重绘它,并且我还尝试将 'fp.setVisibility(ImageView.VISIBLE)' 从 try-catch 块中取出,但两者都没有用。 (其中后者显然不起作用,我真的没想到它会起作用,但我真的很绝望:P)我现在已经搜索了几个小时,并且 none 的 Whosebug-pages和其他 fora/documentation 有这个问题的答案。在循环继续到下一个之前,如何确保焦点绘制?

使用Thread.sleep(ms) 延迟UI 线程是一个非常危险的想法,如您所见,它不会导致任何结果。通过阻塞线程 16 秒,您可以有效地冻结该期间的应用程序 - 包括在此期间可能发生的任何重绘和其他事件处理。永远不要那样做。

相反,使用 Handler 及其 postDelayed(Runnable, ms) 方法来安排将来的可见性更改。处理程序通过向事件循环添加消息来工作,因此它们不会破坏正常行为。

检查您代码的修改版本:

private static final long FP_SHOW_DELAY_MS = 1000;
private Handler handler = new Handler();

public void performExperiment (View v) {
    Log.i(TAG, "Experiment has started on view: " + v);
    final ArrayList<FocusPoint> permutation = new ArrayList<>(Arrays.asList(focusPoints));
    Collections.shuffle(permutation);

    for (int i = 0; i < permutation.size(); i++) {
        final FocusPoint fp = permutation.get(i);

        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                fp.setVisibility(View.VISIBLE);
            }
        }, (i + 1) * FP_SHOW_DELAY_MS);
    }
}