为什么我的Android转换会忽略TransitionListener?

时间:2015-12-28 17:57:54

标签: android xamarin.android android-transitions

我尝试在更新显示之前调用TransitionManager.beginDelayedTransition(viewGroup, new AutoTransition())来平滑更新显示。但我发现有时候我会快速更新显示屏并且Android会感到困惑。

所以我向TransitionListener添加了AutoTransition,其中transitionEnd()回拨,说过渡已完成,此时我会动画显示屏幕的新状态。但我发现通常甚至都没有这个。

当a)转换结束或b)转换永远不会被调用时,是否有某种方法可以回调回叫?

更多信息:

我正在使用Xamarin.Android。我有一段看起来像这样的代码启动转换:

if (animated && viewGroup != null && Utils.Api19PlusKitkat) {
    App.Log("** Beginning animation.");
    var transition = new AutoTransition();
    transition.AddListener(new TransitionListener(this));
    TransitionManager.BeginDelayedTransition(viewGroup, transition);
}

TransitionListener非常简单:

public class TransitionListener : Java.Lang.Object, Transition.ITransitionListener {
    readonly TreeNode owner;

    public TransitionListener(TreeNode owner)
    {
        this.owner = owner;
    }

    public void OnTransitionEnd(Transition transition)
    {
        App.Log("**** TransitionListener: Transition End.");
        owner.FinishTransition();
    }

    public void OnTransitionCancel(Transition transition) {}
    public void OnTransitionPause(Transition transition) {}
    public void OnTransitionResume(Transition transition) {}
    public void OnTransitionStart(Transition transition) {
        App.Log("**** TransitionListener: Transition Start.");
    }
}

当我查看我的应用程序日志时,我看到了一堆" Beginning animation"但非常罕见的过渡开始"或者"过渡结束" (目前我没有看到任何情况,但有时我会在日志中看到它。)

2 个答案:

答案 0 :(得分:3)

<强> UPD2:

我想,我现在明白了。经过2天毫无结果的尝试,我成功地重新解决了这个问题。

当屏幕上有更新内容时,

TransitionManager.beginDelayedTransition()会启动

例如,如果setOnClickListener TransitionManager.beginDelayedTransition()位于OnClick的自定义背景而非选择器(android:background="#000",而不是默认选择器)的按钮,则不会发生任何事情,Transition根本不会启动(如您所见)。同时,如果您将相同的OnClickListener分配给默认样式按钮(即选择器作为背景),Transition 立即启动。

同样,如果在调用TransitionManager.beginDelayedTransition()后进行一些UI更改:

public void changeScene(View v){
    AutoTransition autoTransition = new AutoTransition();
    autoTransition.setDuration(3000);
    autoTransition.addListener(new Transition.TransitionListener() {
        @Override
        public void onTransitionStart(Transition transition) {
            Toast.makeText(MainActivity.this, "start", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onTransitionEnd(Transition transition) {
            Toast.makeText(MainActivity.this, "end", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onTransitionCancel(Transition transition) {}

        @Override
        public void onTransitionPause(Transition transition) {}

        @Override
        public void onTransitionResume(Transition transition) {}
    });

    TransitionManager.beginDelayedTransition(container, autoTransition);
    findViewById(R.id.btn1).setVisibility(
            (findViewById(R.id.btn1).getVisibility()) == View.VISIBLE?
                     View.INVISIBLE : View.VISIBLE);
}

这将使代码片段正常工作:

enter image description here

但是一旦删除了Visibility的setter,Transition就会添加到TransitionManager backlog 并且没有执行(方法名称显示 - 它可能延迟)。它将仅在下一次UI更改期间执行:

enter image description here

在这个例子中,我删除了setVisibility() - 你可以看到结果:“动画”(在我的情况下只是Toasts)只有在我点击按钮并选择Selector作为背景后才启动(即UI - 发生变化)。

因此修复将会是 - “确保在您致电TransitionManager.beginDelayedTransition()之后有一些用户界面更改。

我希望,这有帮助

P.S。但有点奇怪,在TransitionManager.go()之后编写的TransitionManager.beginDelayedTransition()将无效。我在这里找到的唯一解决方法是将其放在onTransitionEnd内以进行延迟转换。

<强> Upd1:

首先想到的是它可能与Xamarin有关。然后我发现了两个在Xamarin.Android中使用BeginDelayedTransition的示例:xamarin/monodroid-samplesgaruma/Moyeu。 要检查你的问题是否与Xamarin.Android有关 - 我建议调试这两个项目,看看TransitionListener是否会触发Transition-events。

两个示例都使用TransitionManager.beginDelayedTransition()和一个参数(viewGroup)。检查TransitionManager显示的source code,该1参数方法正在调用beginDelayedTransition(sceneRoot, null);

public static void beginDelayedTransition(final ViewGroup sceneRoot) {
    beginDelayedTransition(sceneRoot, null);
}

和null替换为sDefaultTransition

private static Transition sDefaultTransition = new AutoTransition();
....
public static void More ...beginDelayedTransition(final ViewGroup sceneRoot, Transition transition) {
    if (!sPendingTransitions.contains(sceneRoot) && sceneRoot.isLaidOut()) {
        if (Transition.DBG) {
            Log.d(LOG_TAG, "beginDelayedTransition: root, transition = " +
                    sceneRoot + ", " + transition);
        }
        sPendingTransitions.add(sceneRoot);
        if (transition == null) {
            transition = sDefaultTransition;
        }
        final Transition transitionClone = transition.clone();
        sceneChangeSetup(sceneRoot, transitionClone);
        Scene.setCurrentScene(sceneRoot, null);
        sceneChangeRunTransition(sceneRoot, transitionClone);
    }
}

因此,要进行调试,您必须获取默认TransactionManager.getDefaultTransition()并将TransitionListener添加到其中。

如果有效 - 那么我们必须在您的代码中找到问题。如果它不起作用 - 那么......大概,我们发现了一个系统错误,我们可以提交。

答案 1 :(得分:0)

我终于找到了问题的答案。

我在TransitionManager.beginDelayedTransition打电话给FrameLayout时我打电话时没有孩子,然后我又加了一个孩子。

这不会导致转换发生,也不会调用回调。

我现在在拨打电话之前检查ViewGroup我打电话beginDelayedTransition是否有孩子。如果它没有,我就不用费心去做动画了。