在此动画侦听器中进行回调的最佳方式是什么?

What would be the best way to do a callback within this animation listener?

在很多地方,我发现自己在我的应用程序中淡入淡出。

我决定创建一个名为 Fade 的助手。

Fade 有一个有问题的方法:

public class Fade {

    public static void hide(final View view, AnimatorListenerAdapter listener) {
        if (view.getVisibility() == View.VISIBLE) {
            view.animate().setDuration(DURATION);
            view.animate().alpha(0f).setListener(listener);
        }
    }

}

为了让 Fade.hide 正常工作,我需要 AnimationListenerAdapter 在其 onAnimationEnd 方法中执行以下操作。请注意,我不只是这样做的原因是因为使用这个助手的人应该能够为衰落开始、结束等时间自定义监听器。

view.setAlpha(1f);
view.setVisibility(View.INVISIBLE);
view.animate().setListener(null);

其中 view 引用了此助手客户端正在使用的视图。

我认为这种行为是非常不可取的,并且让我怀疑是否值得拥有帮助者。

我不能只让使用助手的人传入 AnimatorListenerAdapter,然后我以某种方式将其填充到我自己的 AnimatorListenerAdapter 中。

我想过做以下事情,但这绝对是 hacky:

public static void hide(final View view, Runnable endAction) {
    if (view.getVisibility() == View.VISIBLE) {
        view.animate().setDuration(DURATION);
        view.animate().alpha(0f).setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                view.setAlpha(1f);
                view.setVisibility(View.INVISIBLE);
                view.animate().setListener(null);

                endAction.run();
           }
        }
    }
}

这看起来很老套,最终需要我制作许多方法签名来解释所有 AnimatorListenerAdapter 回调,如 onAnimationRepeat、onAnimationStart 等

有没有什么办法可以缓解这种情况,或者我应该减少代码异味并只在 类 做很多褪色的情况下创建相同的方法?

您可以做的是有一个组合 AnimatorListenerAdapter,它包装提供的侦听器并在完成所需的工作后委托调用。例如:

public final class FadeHelper {
    public static void fade(final View view, Animator.AnimatorListener listener) {
        if (view.getVisibility() == View.VISIBLE) {

            // Create a composite listener and override onAnimationEnd()
            // to do your own thing, then call through to super to pass
            // the event to the provided listener.
            final Animator.AnimatorListener compositeListener = new CompositeAnimatorListenerAdapter(listener) {
                @Override
                public void onAnimationEnd(Animator animator) {
                    view.setAlpha(1f);
                    view.setVisibility(View.INVISIBLE);

                    // Not sure why this line is necessary?
                    view.animate().setListener(null);

                    // This passes the event to the original listener
                    super.onAnimationEnd(animator);
                }
            });

            view.animate()
                .setDuration(DURATION)
                .alpha(0f)
                .setListener(compositeListener);
        }
    }

    private static class CompositeAnimatorListenerAdapter implements Animator.AnimatorListener {
        private final Animator.AnimatorListener mDelegate;

        public CompositeAnimatorListenerAdapter(Animator.AnimatorListener delegate) {
            mDelegate = delegate;
        }

        @Override
        public void onAnimationStart(Animator animator) {
            if (mDelegate != null) {
                mDelegate.onAnimationStart(animator);
            }
        }

        @Override
        public void onAnimationEnd(Animator animator) {
            if (mDelegate != null) {
                mDelegate.onAnimationEnd(animator);
            }
        }

        @Override
        public void onAnimationCancel(Animator animator) {
            if (mDelegate != null) {
                mDelegate.onAnimationCancel(animator);
            }
        }

        @Override
        public void onAnimationRepeat(Animator animator) {
            if (mDelegate != null) {
                mDelegate.onAnimationRepeat(animator);
            }
        }
    }
}