igo*_*jrr 6 android android-fragments
是否有可能保持一个片段一边跑一边叫我replace从FragmentManager打开一个新的片段?
基本上我不想在导航(通过replace方法)到另一个片段时暂停片段.
可能吗?或者正确的方法是,每当我需要打开它并恢复其先前的状态时,总是会实例化一个新的片段?
谢谢!
Rez*_*adi 11
FragmentManger replace方法将完全破坏前一个片段,因此在每个事务onDestroyView(),onDestroy()和onDetach()都将在前一个片段上调用.如果你想保持你的片段运行,你可以使用FragmentManger hide()和show()方法!它隐藏并显示碎片而不破坏它们.
所以首先将两个片段添加到片段管理器中,并隐藏第二个片段.
fragmentManager.beginTransaction()
.add(R.id.new_card_container, FragmentA)
.add(R.id.new_card_container,FragmentB)
.hide(FragmentB)
.commit();
Run Code Online (Sandbox Code Playgroud)
请注意,您只能在隐藏片段上调用show().所以在这里你不能在FragmentA上调用show(),但这不是问题,因为通过隐藏和显示FragmentB你可以获得你想要的替换效果.
这是一种在片段之间来回切换的方法.
public void showOtherFragment() {
if(FragmentB.isHidden()){
fragmentManager.beginTransaction()
.show(FragmentB).commit();
} else {
fragmentManager.beginTransaction()
.hide(FragmentB).commit();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,如果您将日志消息放入片段回调方法中,您将看到没有破坏(除了屏幕方向更改!),甚至视图也不会被破坏,因为onDistroyView没有被调用.
只有一个问题就是,第一次应用程序启动onCreateView()方法时会为每个片段调用一次(它应该是!)但是当方向更改onCreateView()时会为每个片段调用两次,这是因为片段一旦像往常一样创建,一次因为FragmentManger的附件(保存在bundle对象上)为了避免你有两个选项1)在onSaveInstaneState()回调中分离片段.
@Override
protected void onSaveInstanceState(Bundle outState) {
fragmentManager.beginTransaction()
.detach(FragmentA)
.detach(FragmentB)
.commit();
super.onSaveInstanceState(outState);
}
Run Code Online (Sandbox Code Playgroud)
它正在工作,但视图状态不会自动更新,例如,如果您有一个EditText,其文本将在每次方向更改发生时擦除.当然,您可以通过在片段中保存状态来解决这个问题,但如果使用第二个选项则不需要!
首先,我在onSaveInstaneState()方法中保存一个布尔值,以记住巫婆片段.
@Override
protected void onSaveInstanceState(Bundle outState) {
boolean isFragAVisible = true;
if(!FragmentB.isHidden())
isFragAVisible = false;
outState.putBoolean("isFragAVisible",isFragAVisible);
super.onSaveInstanceState(outState);
}
Run Code Online (Sandbox Code Playgroud)
现在在活动onCreate方法我检查以查看savedInstanceState == null.如果是,那么如果没有活动是第二次创建的话.所以片段管理器已经包含了片段.所以我得到了片段管理器中我的片段的引用.我也确保显示正确的片段,因为它没有自动恢复.
fragmentManager = getFragmentManager();
if(savedInstanceState == null){
FragmentA = new FragmentA();
FragmentB = new FragmentB();
fragmentManager.beginTransaction()
.add(R.id.new_card_container, FragmentA, "fragA")
.add(R.id.new_card_container, FragmentB, "fragB")
.hide(FragmentB)
.commit();
} else {
FragmentA = (FragmentA) fragmentManager.findFragmentByTag("fragA");
FragmentB = (FragmentB) fragmentManager.findFragmentByTag("fragB");
boolean isFragAVisible = savedInstanceState.getBoolean("isFragAVisible");
if(isFragAVisible)
fragmentManager.beginTransaction()
.hide(FragmentB)
.commit();
else
fragmentManager.beginTransaction()
.hide(FragmetA) //only if using transaction animation
.commit();
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,如果不使用事务动画,您的片段将完美运行.如果这样做,您还需要显示和隐藏FragmentA.因此,当你想显示FragmentB时,首先隐藏FragmentA然后显示FragmentB(在同一个事务中),当你想要隐藏FragmentB时首先隐藏它并同时显示FragmentA(再次在同一个事务中).这是我的卡片翻转动画代码(从developer.goodle.com下载)
public void flipCard(String direction) {
int animationEnter, animationLeave;
if(direction == "left"){
animationEnter = R.animator.card_flip_right_in;
animationLeave = R.animator.card_flip_right_out;
} else {
animationEnter = R.animator.card_flip_left_in;
animationLeave = R.animator.card_flip_left_out;
}
if(cardBack.isHidden()){
fragmentManager.beginTransaction()
.setCustomAnimations(animationEnter, animationLeave)
.hide(cardFront)
.show(cardBack)
.commit();
} else {
fragmentManager.beginTransaction()
.setCustomAnimations(animationEnter,animationLeave)
.hide(cardBack)
.show(cardFront)
.commit();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3570 次 |
| 最近记录: |