Ошибка: Theme.Translucent & FLAG_ACTIVITY_REORDER_TO_FRONT
У меня есть активность с полупрозрачной темой:
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
android:launchMode
из singleTask
или singleInstance
не нужны. Они изменяют заднюю часть и перемещают действия в их собственный стек. Поэтому мы больше не имеем 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
Ответы
Ответ 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);
}
Ответ 2
launchMode
должен быть singleTask
в теге <activity>
вашей активности в файле манифеста.
Из документации:
singleTask - Если при запуске операции уже есть задача который начинается с этого действия, затем вместо запуска нового Например, текущая задача доведена до фронта. Существующий экземпляр получит вызов Activity.onNewIntent()
с новым Запуск, который начинается, и с Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
установлен флаг. Это надмножество режим singleTop, где, если уже есть экземпляр активность начинается в верхней части стека, она будет получать Намерение, описанное здесь (без FLAG_ACTIVITY_BROUGHT_TO_FRONT
флаг).
Update
В качестве лучшего обходного пути вы можете попробовать сделать недействительным все окно в onNewIntent()
или в onResume
..
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
getWindow().getDecorView().invalidate();
}
Ответ 3
Как обход не ответ
Я сделал это:
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);
}
}
если кто-нибудь может дать мне ответ, он выиграет бонус brucey!
Ответ 4
Я просто удалил 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
* Manifest *
<?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>
Ответ 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();
}
}
С этим кодом нам не нужно использовать флаг FLAG_ACTIVITY_REORDER_TO_FRONT
при запуске FirstAct
позже, так как в фоновом режиме используйте SavedState
из его предыдущей копии в качестве исходного состояния новой копии.
Обратите внимание, что в моем примере кода я просто уничтожил старую копию FirstAct
(вызывая finish()
после сохранения состояния экземпляра фрагмента) в onPause()
. Более серьезная реализация, вероятно, установила бы флаг (для проверки в onResume()
), должна ли конкретная копия быть finish()
изменена при повторном просмотре в стеке (если она была "перенесена вперед" в качестве более новой копии).
Ответ 6
У меня была такая же проблема. Я переместил тег использования-разрешения перед тегом приложения в AndroidManifest.xml. Это исправило это для меня.