如何知道一项活动是不是在没有过渡的情况下开始?

Posted

技术标签:

【中文标题】如何知道一项活动是不是在没有过渡的情况下开始?【英文标题】:How can one know if an activity is started without a transition?如何知道一项活动是否在没有过渡的情况下开始? 【发布时间】:2016-06-04 10:35:19 【问题描述】:

我有一个用例,我主要通过转换启动一个活动,但从导航抽屉打开它时不是这种情况。

为了保持过渡平稳,我有一个Transition.TransitionListener,在过渡完成时我会在其中触发一些 UI 更新。

所以我有这样的事情:

public class SomeActivity extends Activity 

    public void onCreate(Bundle savedInstanceState) 
        // ...
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) 
            Transition sharedElementEnterTransition = getWindow().getSharedElementEnterTransition();
            sharedElementEnterTransition.addListener(new Transition.TransitionListener() 
                // ...
                @Override
                public void onTransitionEnd(Transition transition) 
                    doSomeUiUpdating();
                
            );
         else  // Pre-Lollipop
            doSomeUiUpdating();
        
    

这在使用动画启动 Activity 时效果很好,但是我如何知道 Activity 是否在没有过渡的情况下启动,以便我可以调用 doSomeUiUpdating()

我确定ActivityWindowTransition 或者我忽略的某个地方一定有一个简单的方法。我不想中继调用 Activity 来设置一些包来告知动画是否正在显示。

【问题讨论】:

我会假设它的逻辑和你一样(if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) doSomeUiUpdating(); ... .) 在代码之前你必须开始一个活动 并且在 API 19 (KITKAT) 中添加了转换,因此您需要在此之前检查不是 LOLLIPOP -- youtube.com/watch?v=K3yMV5am-Xo 问题是 - 正如我在第一行中所说的那样 - 活动(即使在 Lollipop+ 上)最常从过渡开始,而不是当用户从导航开始活动时抽屉。 不确定你的意思,但你可以等一会,直到导航抽屉关闭,如果这是一个问题,然后再做一些事情 -- developer.android.com/intl/ru/reference/android/support/v4/… 从导航抽屉打开活动时,我没有共享元素(ImageView)来为下一个活动设置动画。 (从其他地方开始活动时,我有共享元素。) 【参考方案1】:

您可以尝试onTransitionStart of TransitionListener 设置一些布尔值isAnimationStarted

public class SomeActivity extends Activity 

    private boolean isAnimationStarted = false;

    public void onCreate(Bundle savedInstanceState)  
        // ...
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) 
            Transition sharedElementEnterTransition = getWindow().getSharedElementEnterTransition();
            sharedElementEnterTransition.addListener(new Transition.TransitionListener() 
                // ...
                @Override
                public void onTransitionEnd(Transition transition) 
                    doSomeUiUpdating();
                

                @Override
                public void onTransitionStarted(Transition transition) 
                    isAnimationStarted = true;
                
            );
        
    

    public void onStart() 
        if (!isAnimationStarted) 
            doSomeUiUpdating();
        
    


【讨论】:

不错且简单的解决方案。 :) 但这不会产生一个可能的问题——因为回调意味着异步执行,难道即使动画即将到来,onStart 会在 onTransitionStarted 被调用之前被调用吗? 事实上,我只是对其进行了测试,正如我所说的那样——在我的例子中,onStart 总是在任何回调之前被调用,所以 isAnimationStarted 在那里总是假的。因此,这种方法当然无助于确定活动是否在有/没有过渡的情况下启动。 您找到正确的方法了吗?正如@NeverwinterMoon 的评论所说,这并不能完全解决问题。【参考方案2】:

由于您要启动 Activity,因此您将使用 Intent 启动它。您可以向Intents 添加额外内容,并在被调用的ActivityonCreate() 中检查它们。

假设我们有 2 个活动 – ActivityAActivityB

现在,假设ActivityA 是调用Activity,而ActivityB 是调用Activity

ActivityA 中,假设您编写了一些代码来以ActivityB 开头SharedElementTransition

@Override
public void onClick(View v) 
    Intent startActivityBIntent = new Intent(getContext(), ActivityB.class);
    startActivityBIntent.putExtra("IS_SHARED_ELEMENT_TRANSITION_ENABLED", true);
    ActivityOptionsCompat activityOptionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(), view, ViewCompat.getTransitionName(view));
    startActivity(startActivityBIntent, activityOptionsCompat);

现在,如果您注意到上面的内容,我已经使用 putExtra() 方法传递了一个 Intent extra。我传递了一个 Boolean 值为 true 的值,因为我打算使用 SharedElementTransition 启动 Activity。

现在在ActivityBonCreate() 方法中,您可以只检查传递给Intent 的布尔值。如果你传递了 false,那么你可以添加一个条件语句并在那里执行你的 UI 更新。我在下面给了你一个小sn-p来帮助你开始:

private static final String isSharedElementTransitionEnabled = "IS_SHARED_ELEMENT_TRANSITION_ENABLED";    

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_b);

    // If you are postponing your SharedElementTransition, don't forget to call postponeEnterTransition() and override onPreDraw()

    if (!getIntent().getExtras().getBoolean(isSharedElementTransitionEnabled)) 
        //Do your UI updation here
    

这样做的好处是,您可以完全控制内容转换和共享元素转换的播放方式。

【讨论】:

以上是关于如何知道一项活动是不是在没有过渡的情况下开始?的主要内容,如果未能解决你的问题,请参考以下文章

通知意图 - 如何在不重置的情况下恢复通知中的活动?

Android:状态栏不是过渡到新活动的主题

UIView.animateKeyframes 跳转到下一个动画的开始而不是平滑过渡

Android - 恢复上次查看的活动

在没有数据的情况下实例化 Handsontable

使用Material Design在Android Lollipop中的ListView中的活动过渡动画