应用程序(目标API级别必须为7)具有FragmentActivity
,它在onCreate
分析作为额外传递的片段密钥。
现在需要的是重新排序已经使用给定片段键创建的活动。
假设具有不同片段密钥的FragmentActivity
为FA1
,FA2
和FA3
- 每个都是具有不同片段的同一活动类实例。
现在在堆栈FA1
> FA2
> FA3
我想使用intent而不是后退按钮来FA2
,默认情况下会给出:
FA1
> FA2
> FA3
>新FA2
。
我想要FA1
> FA3
> FA2
FA3
可能有一些待处理的操作,FA1
> FA2
不是很好但绝对比默认更好。
如果有多个活动,我会使用FLAG_ACTIVITY_REORDER_TO_FRONT
标记进行意图,但这不适用于这种情况。
FA1, FA2, FA3, etc.
是同一个类MyFA
的所有实例,这就是为什么我无法使用intent标志,并且FragmentManager似乎没有帮助,直到有一个标准的全局片段缓存
里程碑(目前工作和待改进)解决方案我今天学到的一件事是activity-alias,它允许为同一活动制作几个别名,使用不同的Intent附加项ID的。现在使用REORDER_TO_FRONT标志它可以正常工作。
解决方案反馈解决方案没有低级操作,我比挖掘任务或后端堆栈更重要。现在的缺点是每个这样的活动需要一个单独的别名与硬编码路径,我真的不喜欢它。
要求(赏金在这里)无论谁进行了不错的优化,都需要 150 300个cookie。不错 ?任何其他固体解决方案也受到高度赞赏。
目前我在应用程序清单中有10个别名,例如
<activity
android:name=".activity.FragmentActivity"
android:configChanges="orientation"
android:screenOrientation="portrait" >
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="com.company.name.intent.FragmentActivity" />
</intent-filter>
</activity>
<activity-alias
android:name="com.company.name.intent.FragmentActivity.FragmentedOne"
android:targetActivity=".activity.FragmentActivity" >
<intent-filter>
<action android:name="com.company.name.intent.FragmentActivity.FragmentedOne" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="fragment_key_extra"
android:value="FragmentOne" />
</activity-alias>
<activity-alias
android:name="com.company.name.intent.FragmentActivity.FragmentedTwo"
android:targetActivity=".activity.FragmentActivity" >
<intent-filter>
<action android:name="com.company.name.intent.FragmentActivity.FragmentedTwo" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="fragment_key_extra"
android:value="FragmentTwo" />
</activity-alias>
然后用
重新排序活动Intent intent = new Intent(
"com.company.name.intent.FragmentActivity.FragmentedOne");
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
答案 0 :(得分:4)
这个答案值300卡:-D Mmmmm
扩展应用程序,以便我们可以创建具有全局范围的自己的后台列表。
import android.app.Application; import android.content.Intent;
类MyApp扩展了Application {
//This is our very own back stack.
private ArrayList<Intent> backStack = new ArrayList<Intent>();
public void reorderBackStack(){
//Do what you want to the order of your backstack
//You can read the value of your intent extras from here.
}
public void addIntent(Intent i){ // this gets called from our activities onCreate
backStack.add(i);
}
public void goBack(){
if(backStack.size() >= 2){ // can go back
backStack.remove(backStack.size() - 1); // drop the last item in stack if you want. This is how Android does it. (no forward capability)
this.startActivity(backStack.get(backStack.size() - 1));
}
}
}
在我们的活动中添加对自定义后台筹码的引用。
公共类MainActivity扩展Activity { MyApp myapp;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myapp = ((MyApp)getApplicationContext());
myapp.addIntent(this.getIntent()); //add the intent for this instance to backStack.
myapp.reorderBackStack(); // call this anytime we need to reorder the back stack.
}
@Override
public void onNewIntent(Intent newIntent){
this.setIntent(newIntent);
myapp.addIntent(this.getIntent());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
// We won't be using the back stack we will be using our own list of intents as a back stack so we need to override the back button.
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
myapp.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
}
覆盖后退按钮,以便我们可以使用自己的后台而不是Android。
修改强>
我把概念证明放在一起。
我的谷歌硬盘上的.apk is Here。
压缩downloadable project folder is here。
请不要抱怨我的代码。我知道我使用了字符串,我应该使用常量,我复制代码而不是分隔它,我的间距不完美,我使用了过多的循环和对象。我还没有整理出savedInstanceState。同样,这只是一个概念证明。它有效,我认为它可能对某人有所帮助。
答案 1 :(得分:2)
您可以查看使用FragmentManager提供的功能。它具有popBackStack
。
您还可以使用FragmentTransaction将片段添加到Backstack中。您可以使用addToBackStack
来完成此任务。
因此,使用这两个类,您应该能够根据需要在backstack中重新排序片段。
答案 2 :(得分:2)
以下是解决方案:
1。在您的FragmentActivity
中实施Interface
,以便从片段到活动进行回调。
2。当您启动任何片段时,将其置于后台堆栈中,并使用参数或标记(addToBackStack(String arg0))
,您可以使用该标记弹出该标记。
3。当您需要对片段进行重新排序时,请根据需要使用适当的参数调用您实现的接口的方法,然后使用popBackStack(String arg1, String arg2)
来获取带有标记的片段你把它放在后台。
答案 3 :(得分:1)
我已经回答了类似的问题,但解决方案并不是最好的,因为FA1&gt; FA2> FA3将带您到FA1&gt; FA2而不是FA1> FA3&gt; FA2。
My answer was for question : How to tag Activity
无论如何,我编写了一些代码来使用一个字符串“tag”,但我认为你可以使用使用整数索引的主要解决方案。总之,这应该允许您fallBackToActivity
具有特定TAG。我不确定每个Activity将如何决定它的标签是什么,但在我之前的回答中,它只是一个增量整数的简单问题。
package sherif.android.stack.overflow;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class SuperActivity extends FragmentActivity {
private static String EXTRA_INDEX = "SUPER_INDEX";
private static int RESULT_FALLBACK = 0x123456;
private String tag; //this is your tag
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(getIntent()!=null) {
tag = getIntent().getStringExtra(EXTRA_INDEX, "default_tag");
}
}
protected final String getIndex() {
return tag;
}
protected final void fallBackToActivity(String tag) {
Intent intent = new Intent();
intent.putExtra(EXTRA_INDEX, tag);
setResult(RESULT_FALLBACK, intent);
finish();
}
//@Override
//public void startActivityForResult(Intent intent, int requestCode) {
// intent.putExtra(EXTRA_INDEX, getIndex());
// super.startActivityForResult(intent, requestCode);
//}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_FALLBACK) {
if(!data.getStringExtra(EXTRA_INDEX, "default_tag").equals(getIndex())) {
setResult(RESULT_FALLBACK, data);
finish();
}
}
}
}
答案 4 :(得分:1)
根据您使用activity-alias
解决此问题的想法,我写了一个Historian class,它将执行以下操作:
startActivity()
和activityDestroyed()
方法,以便查找表可用于根据Intent为正在运行的Activity动态分配别名。以下是如何使用它的示例:
<activity android:name=".MyFragmentActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity-alias android:name=".Alias0" android:targetActivity=".MyFragmentActivity" />
<activity-alias android:name=".Alias1" android:targetActivity=".MyFragmentActivity" />
<activity-alias android:name=".Alias2" android:targetActivity=".MyFragmentActivity" />
<activity-alias android:name=".Alias3" android:targetActivity=".MyFragmentActivity" />
<activity-alias android:name=".Alias4" android:targetActivity=".MyFragmentActivity" />
public class MyFragmentActivity extends FragmentActivity
implements Historian.Host {
private Historian<MyFragmentActivity> mHistorian;
// ...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHistorian = new Historian<MyFragmentActivity>(this);
// ...
}
@Override
protected void onDestroy() {
super.onDestroy();
mHistorian.activityDestroyed(this);
}
@Override
public boolean matchIntent(Intent intent0, Intent intent1) {
if (intent0 == null || intent1 == null) return false;
final String title0 = intent0.getStringExtra("title");
final String title1 = intent1.getStringExtra("title");
return title0.equals(title1);
}
// ...
}
而不是像这样开始你的活动的新实例:
Intent intent = new Intent(this, MyFragmentActivity.class);
intent.putExtra("title", newActivityTitle);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
你这样做:
Intent intent = new Intent(this, MyFragmentActivity.class);
intent.putExtra("title", newActivityTitle);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
mHistorian.startActivity(this, intent);
因此,您仍需要手动向清单中添加一些activity-alias
(用作池)并在Activity中实现matchIntent()
方法(以帮助检测两个Intent是否等于())其余部分由Historian类动态处理。
我没有详尽地测试代码,但它似乎在我做的一些简单测试上工作正常。这个想法实际上与my answer上的other question非常相似(只需要使用FLAG_ACTIVITY_CLEAR_TOP
而不是FLAG_ACTIVITY_REORDER_TO_FRONT
),但使用activity-alias
代替内部{{1}}子课使它更清洁:)