Android中的一个令人讨厌的任务已经访问过我,这是维护片段在Orientation上的状态变化。
首先,我已经尝试了StackOver流程中的每个解决方案,而且我只有一个很好的结果,我没有要求。
我能够在方向更改中维护Fragment中的更改,但是当用户切换片段时无法保存片段状态,因此我已经删除了此解决方案并寻找新的更好的解决方案。
我的想法是显示/隐藏片段,而不需要将它们整体替换,因为它们只会被隐藏一小段时间,如果它们不再可见,再次创建它们就没有问题。 / p>
少说话,更多代码。
int mID = (int) drawerItem.getIdentifier();
String mTag = "";
switch (mID){
case 0:
mTag = "ViewPager";
break;
case 1:
mTag = "Browser";
break;
case 2:
mTag = "Settings";
break;
}
if (savedInstanceState == null) {
ShowHideFrags(mID);
} else {
switch (mID){
case 0:
Log.i("ASDSADSA","4");
mViewPager = (ViewPagerFragment) getSupportFragmentManager().findFragmentByTag(mTag);
ShowHideFrags(mID);
break;
case 1:
Log.i("ASDSADSA","5");
mWebFrag = (WVFragment) getSupportFragmentManager().findFragmentByTag(mTag);
ShowHideFrags(mID);
break;
case 2:
Log.i("ASDSADSA","6");
mSettings = (SettingsFragment) getSupportFragmentManager().findFragmentByTag(mTag);
ShowHideFrags(mID);
break;
}
}
此代码处理导航抽屉中的点击,我在Mikepenz
使用'Material Drawer'库。
如代码所示,我有三个片段,分别为ViewPager
,Browser
和Settings
。
我的问题是,它重新创建,没有方向和getFragment
方法,代码中没有问题,但是当我添加对此更改的支持时,片段会再次重新创建。我已经多次尝试更改代码,记录更改,看看有什么问题。
在第一次启动时,它会调用ShowHideFrags(int x)
方法,然后转到else
。
ShowHideFrags(int x)的代码:
private void ShowHideFrags(int SelectedFrag){
if(mFragmentManager == null)
mFragmentManager = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction ft = mFragmentManager.beginTransaction();
switch (SelectedFrag){
case 0:
if(mViewPager == null)
mViewPager = new ViewPagerFragment();
if(!mViewPager.isAdded())
ft.add(R.id.fragment,mViewPager,"Viewpager");
if(!mViewPager.isVisible()){
if((mSettings != null && mSettings.isVisible()))
ft.hide(mSettings);
if((mWebFrag != null && mWebFrag.isVisible()))
ft.hide(mWebFrag);
ft.show(mViewPager);
} else {
if((mSettings != null && mSettings.isVisible()))
ft.hide(mSettings);
if((mWebFrag != null && mWebFrag.isVisible()))
ft.hide(mWebFrag);
}
ft.commit();
break;
case 1:
if(mWebFrag == null)
mWebFrag = new WVFragment();
if(!mWebFrag.isAdded())
ft.add(R.id.fragment,mWebFrag,"Browser");
if(!mWebFrag.isVisible()) {
if((mSettings != null && mSettings.isVisible()))
ft.hide(mSettings);
if(mViewPager != null && mViewPager.isVisible())
ft.hide(mViewPager);
ft.show(mWebFrag);
} else {
if((mSettings != null && mSettings.isVisible()))
ft.hide(mSettings);
if((mViewPager != null && mViewPager.isVisible()))
ft.hide(mViewPager);
}
ft.commit();
break;
case 2:
if(mSettings == null)
mSettings = new SettingsFragment();
if(!mSettings.isAdded())
ft.add(R.id.fragment,mSettings,"Settings");
if(!mSettings.isVisible()) {
if((mViewPager != null && mViewPager.isVisible()))
ft.hide(mViewPager);
if((mWebFrag != null && mWebFrag.isVisible()))
ft.hide(mWebFrag);
ft.show(mSettings);
} else {
if((mViewPager != null && mViewPager.isVisible()))
ft.hide(mViewPager);
if((mWebFrag != null && mWebFrag.isVisible()))
ft.hide(mWebFrag);
}
ft.commit();
break;
}
}
我的onSaveInstanceState代码:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
try{
long mSelectedItem = result.getCurrentSelection();
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.Fragment currentFragment = fragmentManager.findFragmentById(R.id.fragment);
getSupportFragmentManager().putFragment(outState,currentFragment.getTag(),currentFragment);
outState.putLong("SelectedItem",mSelectedItem);
} catch (Exception e){
e.printStackTrace();
}
}
答案 0 :(得分:0)
所以在尝试解决方案4天后,我坐下来喝了一杯,然后我找到了解决这个恼人问题的方法。
由于我在解释进度或步骤方面不是那么棒,我会直截了当地尽力做到亲们的答案。
首先,由于我的应用程序有一个导航抽屉,并且我想显示/隐藏片段而不重新创建它们,所以在不花费太多时间的情况下实现这样的任务是一项艰巨的任务,所以我需要了解生命周期和发生的事情,因此我已经将Log添加到每一步,以了解引擎盖下发生了什么。
当应用启动时,您只切换片段.show()
和.hide()
,该捆绑包将为空。因此
if (savedInstanceState == null) {
LogMessage("Bundle Is Null, normal stuff");
ShowHideFrags(mID);
}
最后将附加使用的方法ShowHideFrags
,其任务仅是检查片段是否为空,并隐藏未选中的片段,并显示所选片段,如果它为空,则方法将创建一个新片段并添加它。
首先很容易,当方向发生时,包不会为空,它将包含已保存的片段,首先我们需要将其保存在包中。
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
long mSelectedItem = result.getCurrentSelection();
try{
FragmentManager mFM = getSupportFragmentManager();
Fragment currentFragment = null;
switch (mTag){
case "ViewPager":
currentFragment = mViewPager;
break;
case "Browser":
currentFragment = mWebFrag;
break;
case "Settings":
currentFragment = mSettings;
break;
}
mFM.putFragment(outState,mTag,currentFragment);
LogMessage(String.format("The following fragment '%1$s' with position %2$s was saved",mTag,String.valueOf(mSelectedItem)));
} catch (Exception e){
e.printStackTrace();
}
outState.putLong("SelectedItem",mSelectedItem);
}
将会问一个问题,为什么使用硬编码字符串而不将它们作为变量?因为我很懒重要提示,不要通过findFragmentByTag
方法保存当前片段,它会为您提供最后应用的片段而不是所选片段,因此我必须手动检查选择的片段是什么。
不要忘记提及片段,我在代码的开头有以下片段
private ViewPagerFragment mViewPager;
private WVFragment mWebFrag;
private SettingsFragment mSettings;
mTag
是片段标记,在导航抽屉中的onClick
方法内,我添加了mTag
值,代码如下:
switch (mID) {
case 0:
mTag = "Viewpager";
break;
case 1:
mTag = "Browser";
break;
case 2:
mTag = "Settings";
break;
}
现在,我们已经分配了mTag,当bundle完成null检查时,也完成了bundle保存部分,现在我们需要在bundle不为null时执行该部分。
首先是代码,然后是解释
if(getSupportFragmentManager().findFragmentByTag(mTag) != null){
LogMessage(String.format("Fragment with tag '%1$s' was found",mTag));
mViewPager = (ViewPagerFragment) getSupportFragmentManager().findFragmentByTag(mTag);
if(!mViewPager.isVisible()) {
LogMessage("Not Visible");
ShowHideFrags(mID);
} else {
LogMessage("Visible");
}
} else {
LogMessage(String.format("Fragment with tag '%1$s' was NOT found", mTag));
if(!ReturnCurrentFragment().equalsIgnoreCase(mTag)){
LogMessage("Not the Same");
ShowHideFrags(mID);
} else {
LogMessage("It's the Same");
}
}
private Fragment ReturnCurrentFragment(){
return getSupportFragmentManager().findFragmentById(R.id.fragment);
}
当bundle不为null时,上面的代码在else子句中。首先我们检查所选片段(保存在包中)是否确实可以加载,如果是,我们分配它,如果它不可见,则意味着其他片段可见,因此我们称之为{{1 }}。
当片段可见时,我们什么都不做。此外,我们检查它是否不在捆绑中,如果不在那里,如果它已经可以重新加载,那么我们不会重新创建它两次* 1.
有了这段代码,我几乎可以解决每一个烦人的错误希望。
ShowHideFrags
的代码:
ShowHideFrags(int x)
* 1:让我们删除该代码块,例如,当片段不在那里,并且该块也不是,并且您尝试切换时,所选片段可能覆盖在前一个片段上,或者可能显示空白一,因此我们需要ShowHideFrags,如果它等于Current片段,所以我们不再重新创建它,并且有两个相同的片段在彼此之上。
希望这个答案对您有所帮助,随时提出并/或更正此答案。