错误:Theme.Translucent & FLAG_ACTIVITY_REORDER_TO_FRONT

Posted

技术标签:

【中文标题】错误:Theme.Translucent & FLAG_ACTIVITY_REORDER_TO_FRONT【英文标题】:Bug : Theme.Translucent & FLAG_ACTIVITY_REORDER_TO_FRONT 【发布时间】:2012-03-07 17:52:31 【问题描述】:

我有一个半透明主题的活动:

android:theme="@android:style/Theme.Translucent.NoTitleBar"

这个问题也可以通过这个主题重现:

<style name="MyTheme" parent="@android:style/Theme">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:colorBackground">@null</item>
</style>

此活动在启动时加载并保存在内存中(当我启动此活动时,我将 FLAG_ACTIVITY_REORDER_TO_FRONT 标志作为额外的广告)。

问题:当我(从菜单)开始这个活动时,活动没有出现,什么也没有发生。 但是:如果我删除半透明主题:一切正常,活动将回到前面。

是 onNewIntent() 被调用。

如果我按下半透明的活动是下面的活动!但它必须是***的。

一个例子

A(半透明活动)B C

堆栈:A

A startActivity(B)

堆栈:A,B

B startActivity(C)

堆栈:A、B、C

c startActivity(A) // 带有标志 FLAG_ACTIVITY_REORDER_TO_FRONT

堆栈应该是:B,C,A

但是 A 永远不会被带到前面,尽管它的 onNewIntent() 被调用了。

有什么想法吗?

附注


有趣的未回答问题:http://groups.google.com/group/android-developers/browse_thread/thread/269c67f6b39cfe45?pli=1


不想使用singleTasksingleInstance 中的android:launchMode。这些会更改后台堆栈并将活动移动到自己的堆栈中。因此,我们不再有 A、B、C。

singleTask 和 singleInstance — 不适合大多数人 应用程序,因为它们产生的交互模型很可能 对用户不熟悉并且与大多数其他人非常不同 应用程序。

http://developer.android.com/guide/topics/manifest/activity-element.html#lmode

任何想要直观表示launchModes的人都可以试试这个应用程序:https://play.google.com/store/apps/details?id=com.novoda.demos.activitylaunchmode

【问题讨论】:

是的,重复了你的场景 android 2.3 检查是否在onNewIntent() 中获得Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT 标志 onNewIntent() 接收FLAG_ACTIVITY_REORDER_TO_FRONT 我认为它按预期工作.. 将窗口背景设置为透明,它不会对眼睛可见.. 如果看到快照会很清楚.. 大约一年半前,有人在Android开发者群发了similar problem。仍然没有回复 【参考方案1】:

如果我们不从AndroidManifest.xml中设置主题,activity block和setContentView之前设置主题,在第一个半透明activity的onCreate方法中,问题就解决了,代码如下:

public class TranslucentActivityDemoActivity extends Activity 

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
      this.setTheme(R.style.myTheme);
        setContentView(R.layout.main);

    

【讨论】:

+1 看起来这确实有效!如果您没有在清单中设置主题,而是在活动中以编程方式设置主题,那么问题就会消失。 我说得太早了 :-( 问题消失了,但背景不再透明。叹息...【参考方案2】:

作为一种解决方法不是答案

我已经这样做了:

public class OverlayActivity extends Activity 

   @Override
   protected void onNewIntent(Intent intent) 
       super.onNewIntent(intent);
       // Restart self when attempting to be brought to front
       Intent restartIntent = new Intent(this, OverlayActivity.class);
       startActivity(restartIntent);
       finish();
   

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

如果有人能给我答案,他们将赢得布鲁西奖金!

【讨论】:

onNewIntent 被调用,但活动没有被带到前台 出于某种原因,你应该使用 setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 来让它工作。 FLAG_ACTIVITY_SINGLE_TOP If set, the activity will not be launched if it is already running at the top of the history stack. 它不在历史堆栈的顶部,但我还是尝试了它,但没有成功。 问题是,我遇到了完全相同的问题:我的活动是 manifest 中的 singleTop 并且 onNewIntent() 被调用但活动没有显示。我不得不添加标志。不知道……可能和半透明主题(bug or sth)有关 我的活动顺便扩展了 FragmentActivity。【参考方案3】:

launchMode 应该是清单文件中活动的&lt;activity&gt; 标记中的singleTask

来自文档:

singleTask - 如果在启动活动时已经有一个任务 从这个活动开始运行,而不是开始一个新的 例如当前任务被带到前面。现有的 实例将收到对 Activity.onNewIntent() 的调用 正在启动的 Intent 以及 Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT 标志集。这是一个超集 singleTop 模式,如果已经存在 活动在栈顶启动,它将收到 那里描述的意图(没有FLAG_ACTIVITY_BROUGHT_TO_FRONT 标志集)。

更新

作为一种更好的解决方法,您可以尝试在 onNewIntent()onResume 中使整个窗口无效..

@Override
protected void onNewIntent(Intent intent) 
   super.onNewIntent(intent);
   getWindow().getDecorView().invalidate();

【讨论】:

The other modes — singleTask and singleInstance — are not appropriate for most applications, since they result in an interaction model that is likely to be unfamiliar to users and is very different from most other applications. Single Instance 会将它带到前面,但是当您继续进行下一个活动时,它会在它自己的任务中,即它自己的后堆栈。这不是上述问题的预期行为。 要注意的另一件事是,您尝试重新排序的活动是任务根。尝试添加另一个活动作为启动活动并让它启动活动 A...如果它有效,那么我们可能有发现了一个错误..但在确认之前需要广泛阅读文档.. 抱歉,这只是作为任务根目录的示例。即使它不是根,它仍然会发生。这与主题有关,我猜它是活动堆栈和windowIsTranslucent 属性的迭代。 我更新了我的答案..尝试将整个窗口重新排序到前面时使其无效.. 不抱歉,不这样做。您是否重新创建了该问题?我可能会写一个小测试项目【参考方案4】:

我刚刚移除了 FLAG,它对我来说一切正常,没有任何问题..第一个活动保持透明并在调用时处于顶部..试一试。

这是我整个示例的代码,

第一幕

public class FirstAct extends Activity 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
       Button btn = new Button(this);
       btn.setText("First Here Go To Second");
       btn.setOnClickListener(new OnClickListener() 

        public void onClick(View v) 
            Intent intent = new Intent(FirstAct.this,SecondAct.class);
            startActivity(intent);
        
    );
       setContentView(btn);
    

第二幕

public class SecondAct extends Activity 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
       Button btn = new Button(this);
       btn.setText("Second Here Go To Third");
       btn.setOnClickListener(new OnClickListener() 

        public void onClick(View v) 
            Intent intent = new Intent(SecondAct.this,ThirdAct.class);
            startActivity(intent);
        
    );
       setContentView(btn);
    

第三幕

public class ThirdAct extends Activity 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
       Button btn = new Button(this);
       btn.setText("Third Here Go To First");
       btn.setOnClickListener(new OnClickListener() 

        public void onClick(View v) 
            Intent intent = new Intent(ThirdAct.this,FirstAct.class);
            //intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
            startActivity(intent);
        
    );
       setContentView(btn);
    

使用 LaunchMode SingleInsance 编辑 Activity *清单*

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.mj.temp"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".FirstAct" android:theme="@android:style/Theme.Translucent.NoTitleBar"  android:launchMode="singleInstance"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="SecondAct" android:launchMode="singleInstance"></activity>
        <activity android:name="ThirdAct" android:launchMode="singleInstance"></activity>
    </application>
</manifest>

【讨论】:

需要的是,在从ThirdAct 启动FirstAct 之后,活动堆栈应该是(SA-TA-FA)。 FA 应该重新排序到堆栈顶部,而不启动它的新实例。在您的示例中,将启动一个新实例,并且活动堆栈将为 (FA-SA-TA-FA)。 @userSeven7s 这也是通过使用 launchMode="singleInstance" 完成的 .. 检查更新的清单文件。 @Frankenstein 在一个更复杂的应用程序中,还有其他导航,中间有这 3 个堆栈场景。 singleInstance 将不起作用。 SingleInstance 使每个活动都成为自己的任务,这意味着从技术上讲,我们没有 FA-SA-TA ,我们有 Stack 1 :Fa ,Stack 2: SA ,Stack 3: TA 。这带来了它自己的复杂性和交互问题。您可以查看这个视觉示例:play.google.com/store/apps/… @Blundell 你可能是对的,我没有那种经验或知识..但是问题说明了 3 个活动,所以我拿了 3 个并检查并发布了我看到的内容..谢谢你的评论检查更多关于 singleInstance..虽然 1 upvote 1 downvote.. @Frankenstein ,我了解,但您的回答表明,每次添加新活动时,您都必须将其声明为 singleInstance。如果你不这样做,那么在此之前的 Activity 将启动,而在此之后的 Activity 将出现这种情况。 A1 ABC 然后当你点击 C1 时你会得到 A,B,C,A1,C1。添加的活动越多,就越奇怪。所以每个活动都是它自己的任务实例是不可行的。【参考方案5】:

这是我的解决方法想法。我相信问题是通过请求将后台堆栈中的半透明活动带到前面来触发的。既然我们做不到,让我们开始一个新的半透明活动副本,而不是从头开始完全重新创建一个,让我们通过使用片段来减少工作量。

因此,如果您的半透明活动看起来像这样(复制自 MKJParekh 的回答):

public class FirstAct extends Activity 
    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        Button btn = new Button(this);
        btn.setText("First Here Go To Second");
        btn.setOnClickListener(new OnClickListener() 
                public void onClick(View v) 
                Intent intent = new Intent(FirstAct.this, SecondAct.class);
                startActivity(intent);
            
        );
        setContentView(btn);
    

我们可以把它转换成这样的:

public class FirstAct extends FragmentActivity 
    private static SavedState mSavedState;
    private FirstFrag mFrag;

    public static class FirstFrag extends Fragment 
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) 
            final Context context = inflater.getContext();
            Button btn = new Button(context);
            btn.setText("First Here Go To Second");
            btn.setOnClickListener(new OnClickListener() 
                public void onClick(View v) 
                    Intent intent = new Intent(context, SecondAct.class);
                    startActivity(intent);
                
            );
            return btn;
            
    

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);    
        mFrag = new FirstFrag();
        if (mSavedState != null) mFrag.setInitialSavedState(mSavedState);
        getSupportFragmentManager()
            .beginTransaction()
            .add(android.R.id.content, mFrag)
            .commit();
    

    @Override
    protected void onPause() 
        super.onPause();
        mSavedState = getSupportFragmentManager().saveFragmentInstanceState(mFrag);
        finish();
        

使用此代码,我们在稍后启动FirstAct 时不需要使用FLAG_ACTIVITY_REORDER_TO_FRONT 标志,因为它将在后台使用其先前副本中的SavedState 作为新副本的初始状态。

请注意,在上面的示例代码中,我只是在其onPause() 中销毁了FirstAct 的旧副本(通过在保存片段实例状态后调用finish())。更严肃的实现可能会设置一个标志(在onResume() 中检查)在堆栈中重新访问特定副本时是否需要finish()ed(如果它已作为较新的副本“带到前面”) .

【讨论】:

【参考方案6】:

我遇到了同样的问题。我在 AndroidManifest.xml 中的应用程序标记之前移动了 uses-permission 标记。这为我解决了问题。

【讨论】:

以上是关于错误:Theme.Translucent & FLAG_ACTIVITY_REORDER_TO_FRONT的主要内容,如果未能解决你的问题,请参考以下文章

EditText双光标问题

Activity设置背景透明之开发坑

Android 系统状态栏一体化

如何设置一个activity透明

如何设置一个activity透明(转)

Android设置Activity背景为透明style的方法