我有我的主要活动actionbaractivity你可以在屏幕上浏览一些碎片,在每个片段上你有imageView
和ListView
,你可以点击任何项目,图像会改变。同样在菜单选项中,您有一个按钮,您可以在其中更改为几乎完全相同的活动:actiobbaractivity两个也可以将此按钮更改为活动一个
我能做的是在滑动碎片时保留图像,但不能通过改变活动来保持碎片的状态。
例如 我正处于片段3的活动中,图像为“某物”。我点击按钮更改为活动二,我在这里做事情然后,我点击按钮更改为活动一,我想看到我的片段3与图像:“东西”而不是默认片段1和默认图片
我为每个活动使用ActionBarActivity,FragmentStatePagerAdapter和Fragment
感谢您的帮助
答案 0 :(得分:0)
根据活动和片段生命周期(http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle和http://developer.android.com/guide/components/fragments.html#Lifecycle),在活动/片段更改之间保持状态的最可靠方法是使用默认API来保存和恢复状态:
当活动/片段被解除时(由于屏幕旋转等配置更改或者因为用户请求转到另一个活动/片段),您可以将其状态保存在Bundle对象中。在创建时,您可以恢复其保存状态,从而重新创建与用户离开的实例完全相同的新实例 - 因此用户感觉没有任何更改。这不依赖于您正在使用的活动/片段的特定子类。
我已经实现了你想要的东西:在我的例子中,一个片段包含一个带按钮的菜单,每个按钮会引导用户到另一个包含带有“后退”按钮的子菜单的片段。因此,如果用户从菜单进入子菜单1,然后回到菜单,然后回到子菜单2,然后回到菜单,最后再回到子菜单1,我希望子菜单1看起来就像用户第一次离开它一样
为此,我创建了:
1)interface
通过我的活动定义我的子菜单类型implemented
,以便他们可以在我的子菜单之间进行更改
2)主通用class
,我的所有子菜单extend
都有一个Bundle
对象来存储他们的状态
3)在我的活动中,我有一个Bundle
数组,能够存储每个子菜单的一个实例(因为我只对恢复最后一个状态感兴趣,所以我不需要多个)
界面(第1项):
public interface SubmenusManager {
public static enum Submenus {
ROOTMENU,
SUBMENU1,
SUBMENU2;
private static final int size = Submenus.values().length;
public static int size() {
return size;
}
public static int getId(Submenus test) {
switch(test) {
case SUBMENU1:
return 1;
case SUBMENU2:
return 2;
case ROOTMENU:
default:
return 0;
}
}
}
public void cloneCurrentSubmenuState(Parcelable toOverwrite);
public Bundle getLastStoredSubmenuState(Submenus submenu);
public void setCurrentSubmenuTo(Submenus submenu);
}
通用类(第2项):
public class MenuFragment extends Fragment {
private Bundle menuData = new Bundle();
public static String RESTORE_MAIN_OBJECT = "restore_main";
public Bundle getMenuData() {
return menuData;
}
public Bundle cloneMenuData() {
return new Bundle(menuData);
}
public void setMenuData(Bundle menuData) {
this.menuData = menuData;
}
}
其中一项活动(第3项):
public class ExampleAct extends FragmentActivity implements SubmenusManager {
/**
* instance variables
*/
private MenuFragment mMenu;
private Bundle [] menuData; // the Array of Bundles!
private static final String CONTAINER = "parcelable_container";
private static final String SUBMENU = "saved_submenu";
private Submenus curSubmenu = Submenus.ROOTMENU; // the default state is the ROOTMENU
private boolean restoreLastSavedState = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) { // first time creating this activity
menuData = new Bundle[Submenus.size()];
} else { // this activity has a saved state from before
// restore all the data from all the submenus
menuData = (Bundle[]) savedInstanceState.getParcelableArray(CONTAINER);
// restore the info about which is the current active submenu
curSubmenu = (Submenus) savedInstanceState.getSerializable(SUBMENU);
}
buildMenuFragment(true);
//(...) stuff
}
private void buildMenuFragment(boolean restoreState) {
// (re)builds fragment inside menu.
// restoreState flags whether activity should look for
// saved state data and restore it
restoreLastSavedState = restoreState;
switch(curSubmenu) {
// Eclipse warns you about which are the constants in your enum
case ROOTMENU:
mMenu = new FragmentRootMenu();
break;
case SUBMENU1:
mMenu = new FragmentSubmenu1();
break;
case SUBMENU2:
mMenu = new FragmentSubmenu2();
break;
}
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.menu_frame, mMenu)
.commit();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(SUBMENU, curSubmenu);
cloneCurrentSubmenuState(mMenu.getMenuData().
getParcelable(MenuFragment.RESTORE_MAIN_OBJECT));
outState.putParcelableArray(CONTAINER, menuData);
// (...) stuff
}
@Override
public void cloneCurrentSubmenuState(Parcelable toOverwrite) {
if (menuData == null) menuData = new Bundle[Submenus.size()];
if (toOverwrite != null)
mMenu.getMenuData().putParcelable(MenuFragment.RESTORE_MAIN_OBJECT, toOverwrite);
menuData[Submenus.getId(curSubmenu)] = mMenu.cloneMenuData();
}
@Override
public Bundle getLastStoredSubmenuState(Submenus forThisSubmenu) {
return
(menuData == null || !restoreLastSavedState) ? new Bundle() : menuData[Submenus.getId(forThisSubmenu)];
}
@Override
public void setCurrentSubmenuTo(Submenus toThisSubmenu) {
if (mMenu != null) {
cloneCurrentSubmenuState(mMenu.getMenuData().
getParcelable(MenuFragment.RESTORE_MAIN_OBJECT));
}
curSubmenu = toThisSubmenu;
buildMenuFragment(true);
}
其中一个子菜单(第2项的扩展名):
public class FragmentSubmenu1 extends MenuFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_submenu1, null);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
init();
}
public void init() {
// (...) stuff
MyParcelableObject tmp = null; // MyParcelableObject is a class
// that implements Parcelable and stores
// relevant info to rebuild this menu
// from a saved state
SubmenusManager m = (SubmenusManager) getActivity(); // remember activity implements SubmenusManager
Bundle bnd = m.getLastStoredSubmenuState(SubmenusManager.Submenus.SUBMENU1);
if (bnd != null) tmp = bnd.getParcelable(MenuFragment.RESTORE_MAIN_OBJECT);
if (tmp == null) {
tmp = new MyParcelableObject();
tmp.buildFromScratch(); // initializes with default data
}
// back button
Button backToMainMenu = (Button) getView().findViewById(R.id.submenu1_back);
backToMainMenu.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((SubmenusManager) getActivity()).
setCurrentSubmenuTo(SubmenusManager.Submenus.ROOTMENU);
}
});
// (...) stuff
}
}
Root菜单(第2项的扩展名):
public class FragmentRootMenu extends MenuFragment {
View myView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myView = inflater.inflate(R.layout.fragment_rootmenu, null);
return myView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
init();
}
public void init() {
Button btnSubmenu1 = (Button) myView.findViewById(R.id.btn_call_submenu1);
btnSubmenu1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((SubmenusManager) getActivity()).
setCurrentSubmenuTo(SubmenusManager.Submenus.SUBMENU1);
}
});
Button btnSubmenu2 = (Button) myView.findViewById(R.id.btn_call_submenu2);
btnSubmenu2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((SubmenusManager) getActivity()).
setCurrentSubmenuTo(SubmenusManager.Submenus.SUBMENU2);
}
});
}
}
为了在活动之间工作,您需要做的就是将存储所有片段的最后状态(在我的情况下,将是Bundle [] menuData
)的对象传递给通过其调用的活动Intent
;你可以像ExampleAct
onCreate()
中那样恢复它。你也可以将Bundle []
包装在一个自定义的Parcelable对象中(非常类似于我的示例MyParcelableObject
;如果使用数组是一个问题,那么我会在HashMap
之内)。
这里是如何在活动之间传递Parcelable: How to send an object from one Android Activity to another using Intents?