为什么我的 Android 过渡会忽略 TransitionListener? [英] Why does my Android transition ignore the TransitionListener?

查看:21
本文介绍了为什么我的 Android 过渡会忽略 TransitionListener?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过在更新显示之前调用 TransitionManager.beginDelayedTransition(viewGroup, new AutoTransition()) 来平滑更新显示.但我发现有时我更新显示很快,Android 就糊涂了.

I'm trying to make a smoothly-updating display by calling TransitionManager.beginDelayedTransition(viewGroup, new AutoTransition()) before updating the display. But I found that sometimes I update the display rapidly and Android gets confused.

所以我在 AutoTransition 中添加了一个 TransitionListener,其中 transitionEnd() 回调,说过渡完成,此时我进行动画处理到屏幕的新状态.但我发现通常这甚至不被调用.

So I added a TransitionListener to the AutoTransition where transitionEnd() calls back, saying the transition is complete, at which point I animate to the new state of the screen. But I find that usually this is not even called.

是否有某种方法可以在 a) 过渡结束或 b) 过渡从一开始就不会被调用时回调回调?

Is there some way of having a callback called back either when a) a transition ends or b) a transition never gets called in the first place?

更多信息:

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

I'm using Xamarin.Android. I have a section of code that looks like this which initiates the transition:

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

TransitionListener 非常简单:

TransitionListener is pretty simple:

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.");
    }
}

当我查看我的应用程序日志时,我看到一堆开始动画"的情况,但过渡开始"或过渡结束"的情况非常罕见(目前我没有看到任何情况,但有时我已经在日志中看到它发生了).

When I look at my application log, I see a bunch of cases of "Beginning animation" but very rare cases of "Transition Start" or "Transition End" (currently I'm not seeing any instances but sometimes I've seen it happen in the log).

推荐答案

Upd2:

我想,我现在明白了.经过 2 天无果的尝试,我设法重现了这个问题.

I think, I got it now. After 2 days of fruitless attempts, I managed to repro the issue.

TransitionManager.beginDelayedTransition()在屏幕上有要更新的内容时触发.

TransitionManager.beginDelayedTransition() will fire up something only when there's something to update on the screen.

例如,如果您在 OnClick 中将 setOnClickListenerTransitionManager.beginDelayedTransition() 设置为带有自定义背景的按钮,而没有选择器 (android:background="#000",而不是默认选择器) - 什么都不会发生,Transition 根本不会开始(如您所见).同时,如果您将相同的 OnClickListener 分配给默认样式的按钮(即选择器作为背景) - Transition 立即开始.

For example, if you setOnClickListener with TransitionManager.beginDelayedTransition() in OnClick to the button with custom background without selector (android:background="#000", instead of the default selector) - nothing will happen, Transition won't start at all (as you see in your case). At the same time, if you assign same OnClickListenerto the default-styled button (i.e. with selector as a background) - Transition will start immediately.

同样,如果你在 TransitionManager.beginDelayedTransition() 被调用后做了一些 UI 改变:

Same, if you do some UI-changes after TransitionManager.beginDelayedTransition() being called:

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

这将代码片段将起作用,因为它应该:

This will code snippet will work, as it should:

但是一旦你移除了 Visibility 的 setter,Transition 就会添加到 TransitionManagerbacklog 并且没有被执行(方法的名称说 - 它可能是 延迟).它只会在下一次 UI 更改时执行:

But once you remove the setter for Visibility, Transition is adding to the backlog of the TransitionManager and not executed (the name of the method says - it might be delayed). And it will be executed only during next UI-change:

在这个例子中,我删除了 setVisibility() - 你可以看到结果:animation"(在我的例子中只是 Toasts)只有在我点击带有 Selector 的按钮后才开始背景(即发生 UI 更改).

In this example, I removed the the setVisibility() - and you can see the result: "animation" (in my case just Toasts) started only after I clicked on the button with Selector as a background (i.e. UI-change happens).

所以修复将是 - 确保在您调用 TransitionManager.beginDelayedTransition() 之后有一些 UI 更改".

So the fix is going to be - "make sure there's some UI change just after you call TransitionManager.beginDelayedTransition()".

希望对你有帮助

附言不过有点奇怪,在 TransitionManager.beginDelayedTransition() 之后编写的 TransitionManager.go() 不起作用.我在这里找到的唯一解决方法是将它放在 onTransitionEnd 中以进行延迟转换.

P.S. It's kind of strange though, that TransitionManager.go(), written after TransitionManager.beginDelayedTransition(), won't work. The only workaround I found here is to put it inside onTransitionEnd for the delayed transition.

更新 1:

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

First thought was that it might be related to Xamarin. Then I found two examples which are using BeginDelayedTransition in Xamarin.Android: xamarin/monodroid-samples and garuma/Moyeu. To check if your issue relates to Xamarin.Android or not - I suggest to debug these 2 projects to see if TransitionListener fires Transition-events.

两个示例都使用带有一个参数 (viewGroup) 的 TransitionManager.beginDelayedTransition().检查 源代码TransitionManager显示,1参数方法是调用beginDelayedTransition(sceneRoot, null);

Both examples uses TransitionManager.beginDelayedTransition() with one parameter (viewGroup). Checking source code of TransitionManager shows, that 1-parameter method is is calling beginDelayedTransition(sceneRoot, null);

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

和 null 替换为 sDefaultTransition:

and null replaces by 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 添加到其中.

So to debug it, you'll have to get the default TransactionManager.getDefaultTransition() and add your TransitionListener into it.

如果它有效 - 那么我们将不得不在您的代码中找到问题.如果它不起作用 - 好吧..那么,大概是我们发现了一个系统错误,我们可以将其归档.

If it works - then we'll have to find the issue in your code. If it doesn't work - well.. Then, presumably, we found a system bug, which we can file.

这篇关于为什么我的 Android 过渡会忽略 TransitionListener?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆