I have an activity which hosts two fragments with only one shown at a time. Effectively the user, through different environmental conditions, should be able to toggle between the two at any given time.
我有一个活动,它主持两个片段,一次只显示一个片段。有效地,用户可以通过不同的环境条件在任何给定时间在两者之间切换。
There is a LoginFragment
which is the first thing the user sees on login, and a LockoutFragment
which may replace the LoginFragment
after a user logs in and we see their account is locked (naturally).
有一个LoginFragment是用户登录时看到的第一件事,还有一个LockoutFragment可以在用户登录后替换LoginFragment,我们看到他们的帐户被锁定(自然)。
That is the typical case, but there is a case in which LockoutFragment
is presented first, if say, the user is using the app and their account is locked for some reason, and we re-open the host activity (LoginActivity
), showing the LockoutFragment
, but giving them a button to "Return to login", which toggles appearance of the LoginFragment
(also naturally).
这是典型的情况,但有一种情况是首先显示LockoutFragment,如果用户正在使用该应用程序并且他们的帐户由于某种原因被锁定,我们重新打开主机活动(LoginActivity),显示LockoutFragment,但给他们一个“返回登录”按钮,切换LoginFragment的外观(也很自然)。
Thus, my goal is to allow a user to toggle between the two fragments, whichever is displayed first. My host activity uses the following functions to achieve this effect:
因此,我的目标是允许用户在两个片段之间切换,无论哪个先显示。我的主机活动使用以下函数来实现此效果:
private void showLockoutFragment() {
if (mLockoutFragment == null) {
mLockoutFragment = new LockoutFragment();
}
transitionToFragment(FRAGMENT_LOCKOUT, mLockoutFragment);
}
private void showLoginFragment() {
if (mLoginFragment == null) {
mLoginFragment = new LoginFragment();
}
transitionToFragment(FRAGMENT_LOGIN, mLoginFragment);
}
private void transitionToFragment(String transactionTag, Fragment fragment) {
if (!getFragmentManager().popBackStackImmediate(transactionTag, 0)) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(
R.animator.fade_in, R.animator.fade_out,
R.animator.fade_in, R.animator.fade_out);
ft.addToBackStack(transactionTag);
ft.replace(R.id.fragment_container, fragment, transactionTag);
ft.commit();
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// non configuration change launch
if (savedInstanceState == null) {
Bundle extras = getIntent().getExtras();
if (extras != null) {
// decide which fragment to show
boolean shouldLockout = extras.getBoolean(EXTRA_SHOULD_LOCKOUT);
if (shouldLockout) {
showLockoutFragment();
} else {
showLoginFragment();
}
} else {
showLoginFragment();
}
} else {
// retrieve any pre-existing fragments
mLoginFragment = (LoginFragment)getFragmentManager().findFragmentByTag(FRAGMENT_LOGIN);
mLockoutFragment = (LockoutFragment)getFragmentManager().findFragmentByTag(FRAGMENT_LOCKOUT);
}
}
These functions work together like a charm, with one exception: when, after initial launch of the app, a user
这些功能像魅力一样工作,但有一个例外:在应用程序首次启动后,用户
- attempts log in,
- is taken to the lockout fragment,
- reorients the device, and
- navigates back to the login fragment,
尝试登录,
被带到了锁定片段,
重新定位设备,和
导航回登录片段,
the login fragment is now present but invisible - as if the popEnter
animation was never played. I know it is present because I can still interact with it.
登录片段现在存在但不可见 - 就好像从未播放过popEnter动画一样。我知道它存在,因为我仍然可以与它互动。
It is also worth noting the following:
值得注意的还有以下几点:
- I have
setRetainInstance(true)
on both fragments - This only occurs when a user reorients the device from the lockout fragment
- I have tried this on both a simulator and device running Lollipop with same results
我对两个片段都有setRetainInstance(true)
仅当用户从锁定片段重新定向设备时才会发生这种情况
我已经在模拟器和运行Lollipop的设备上尝试了相同的结果
Is it possible that the back stack is being corrupted after reorientation?
重新定位后后堆栈是否可能被损坏?
Thank you!
1 个解决方案
#1
0
Ok, so it turns out the issue actually lies in my use of setRetainInstance
. According to the docs for that method:
好的,事实证明问题实际上在于我使用了setRetainInstance。根据该方法的文档:
Control whether a fragment instance is retained across Activity re-creation (such as from a configuration change). This can only be used with fragments not in the back stack. [emphasis mine]
控制是否在活动重新创建(例如从配置更改)中保留片段实例。这只能用于不在后栈中的片段。 [强调我的]
While this appears rather cryptic to me, it seems that using setRetainInstance(true)
on a fragment that is on the back stack could simply have unintended consequences. In my case, the fragment seemed to be retained, but its popEnter
animation was never being called (post-rotation). Again, weird, but I guess just avoid that combination.
虽然这对我来说显得相当神秘,但似乎在后端堆栈上使用setRetainInstance(true)可能会产生意想不到的后果。在我的例子中,片段似乎被保留,但它的popEnter动画从未被调用(旋转后)。再次,奇怪,但我想避免这种组合。
#1
0
Ok, so it turns out the issue actually lies in my use of setRetainInstance
. According to the docs for that method:
好的,事实证明问题实际上在于我使用了setRetainInstance。根据该方法的文档:
Control whether a fragment instance is retained across Activity re-creation (such as from a configuration change). This can only be used with fragments not in the back stack. [emphasis mine]
控制是否在活动重新创建(例如从配置更改)中保留片段实例。这只能用于不在后栈中的片段。 [强调我的]
While this appears rather cryptic to me, it seems that using setRetainInstance(true)
on a fragment that is on the back stack could simply have unintended consequences. In my case, the fragment seemed to be retained, but its popEnter
animation was never being called (post-rotation). Again, weird, but I guess just avoid that combination.
虽然这对我来说显得相当神秘,但似乎在后端堆栈上使用setRetainInstance(true)可能会产生意想不到的后果。在我的例子中,片段似乎被保留,但它的popEnter动画从未被调用(旋转后)。再次,奇怪,但我想避免这种组合。