Bug:Theme.Translucent& FLAG_ACTIVITY_REORDER_TO_FRONT

时间:2012-02-16 10:18:34

标签: android android-intent android-activity stack transparency

我有半透明主题的活动:

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

     

Stack:A

     

startActivity(B)

     

堆叠:A,B

     

B startActivity(C)

     

堆叠:A,B,C

     

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

     

Stack 应为:B,C,A

     

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

有什么想法吗?

附注


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


不希望使用android:launchModesingleTask的{​​p> singleInstance。这些更改了backstack并将活动移动到自己的堆栈中。因此,我们不再有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

6 个答案:

答案 0 :(得分:1)

如果我们没有从AndroidManifest.xml设置主题,活动块并在setContentView之前设置主题,在第一个半透明活动的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 :(得分:0)

清单文件中活动的launchMode标记中的singleTask应为<activity>

来自文档:

  

singleTask - 如果在启动活动时,已经有了一项任务   以此活动开始的运行,而不是开始新的   例如,当前任务被带到前面。现有的   实例将接收到对Activity.onNewIntent()的新呼叫   正在开始的意图,并与   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();
}

答案 2 :(得分:0)

作为解决方法不是答案

我做到了:

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

如果有人能给我答案,他们就赢得了布鲁斯奖金!

答案 3 :(得分:0)

我只是删除了FLAG,而且一切正常对我来说,没有任何问题。第一个活动保持透明状态并在调用时获得最佳状态。只需尝试。

这是我整个例子的代码,

<强> FirstAct

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

<强> SecondAct

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

<强> ThirdAct

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编辑活动 * 清单 *

<?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>

答案 4 :(得分:0)

这是我的解决方法。我认为这个问题是通过要求将后端的半透明活动带到前线来触发的。由于我们不能这样做,让我们开始一个半透明活动的新副本,但不是从头开始重新创建一个,让我们通过利用片段来减少工作量。

所以如果您的半透明活动看起来像这样(复制自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();
    }    
}

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

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

答案 5 :(得分:-1)

我有同样的问题。我在AndroidManifest.xml中的apps标签之前移动了uses-permission标签。这为我解决了。