我在一个活动中有多个片段。在按钮上单击我开始一个新片段,将其添加到backstack。我自然希望调用当前Fragment的onPause()
方法和新Fragment的onResume()
。好吧,它没有发生。
public class LoginFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.login_fragment, container, false);
final FragmentManager mFragmentmanager = getFragmentManager();
Button btnHome = (Button)view.findViewById(R.id.home_btn);
btnHome.setOnClickListener(new View.OnClickListener() {
public void onClick(View view){
HomeFragment fragment = new HomeFragment();
FragmentTransaction ft2 = mFragmentmanager.beginTransaction();
ft2.setCustomAnimations(R.anim.slide_right, R.anim.slide_out_left
, R.anim.slide_left, R.anim.slide_out_right);
ft2.replace(R.id.middle_fragment, fragment);
ft2.addToBackStack("");
ft2.commit();
}
});
}
@Override
public void onResume() {
Log.e("DEBUG", "onResume of LoginFragment");
super.onResume();
}
@Override
public void onPause() {
Log.e("DEBUG", "OnPause of loginFragment");
super.onPause();
}
}
public class HomeFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.login_fragment, container, false);
}
@Override
public void onResume() {
Log.e("DEBUG", "onResume of HomeFragment");
super.onResume();
}
@Override
public void onPause() {
Log.e("DEBUG", "OnPause of HomeFragment");
super.onPause();
}
}
我的期望是,
onPause()
和onResume()
HomeFragment 被调用onPause()
和 LoginFragment 的onResume()
被召唤。我得到的是,
这是正常行为吗?当我按下后退按钮时,为什么没有调用 LoginFragment 的onResume()
。
答案 0 :(得分:159)
只有在调用活动onResume()
或onPause()
时才会调用片段onResume()
或onPause()
。
它们与Activity
紧密耦合。
答案 1 :(得分:18)
ft2.replace()
,FragmentTransaction.remove()
方法被调用,Loginfragment
将被删除。
请参阅this。
因此onStop()
LoginFragment
将被调用而不是onPause()
。 (作为新的
片段完全取代旧片段。)ft2.addtobackstack()
,Loginfragment
的状态将是
保存为捆绑包,当您单击HomeFragment
的后退按钮时,
onViewStateRestored()
将跟随onStart()
LoginFragment
。因此最终不会调用onResume()
。答案 2 :(得分:10)
这里是我更强大的Gor的答案(使用fragments.size()是不可靠的,因为弹出片段后大小不会减少)
getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
if (getFragmentManager() != null) {
Fragment topFrag = NavigationHelper.getCurrentTopFragment(getFragmentManager());
if (topFrag != null) {
if (topFrag instanceof YourFragment) {
//This fragment is being shown.
} else {
//Navigating away from this fragment.
}
}
}
}
});
' getCurrentTopFragment'方法:
public static Fragment getCurrentTopFragment(FragmentManager fm) {
int stackCount = fm.getBackStackEntryCount();
if (stackCount > 0) {
FragmentManager.BackStackEntry backEntry = fm.getBackStackEntryAt(stackCount-1);
return fm.findFragmentByTag(backEntry.getName());
} else {
List<Fragment> fragments = fm.getFragments();
if (fragments != null && fragments.size()>0) {
for (Fragment f: fragments) {
if (f != null && !f.isHidden()) {
return f;
}
}
}
}
return null;
}
答案 3 :(得分:8)
如果你真的想要替换另一个片段中的片段,你应该使用Nested Fragments。
在您的代码中,您应该替换
final FragmentManager mFragmentmanager = getFragmentManager();
与
final FragmentManager mFragmentmanager = getChildFragmentManager();
答案 4 :(得分:3)
getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
List<Fragment> fragments = getFragmentManager().getFragments();
if (fragments.size() > 0 && fragments.get(fragments.size() - 1) instanceof YoureFragment){
//todo if fragment visible
} else {
//todo if fragment invisible
}
}
});
但如果有多个片段可见,请小心
答案 5 :(得分:2)
我有一个非常类似于你的代码,如果它适用于onPause()和onResume()。更改片段时,这些功能分别被激活。
片段中的代码:
@Override
public void onResume() {
super.onResume();
sensorManager.registerListener(this, proximidad, SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this, brillo, SensorManager.SENSOR_DELAY_NORMAL);
Log.e("Frontales","resume");
}
@Override
public void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
Log.e("Frontales","Pause");
}
更改片段时记录:
05-19 22:28:54.284 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:28:57.002 2371-2371/madi.cajaherramientas E/Frontales: Pause
05-19 22:28:58.697 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:29:00.840 2371-2371/madi.cajaherramientas E/Frontales: Pause
05-19 22:29:02.248 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:29:03.718 2371-2371/madi.cajaherramientas E/Frontales: Pause
碎片onCreateView:
View rootView;
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.activity_proximidad, container, false);
ButterKnife.bind(this,rootView);
inflar();
setTextos();
return rootView;
}
当我向后脉冲时(在我加载片段的活动中)动作:
@Override
public void onBackPressed() {
int count = getFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
} else {
getFragmentManager().popBackStack();
}
}
答案 6 :(得分:1)
您简单无法向片段添加片段。这需要在FragmentActivity中发生。我假设您正在FragmentActivity中创建LoginFragment,因此为了使其正常工作,您需要在登录关闭时通过FragmentActivity添加HomeFragment。
一般来说,您需要一个FragmentActivity类,从而将每个Fragment添加到FragmentManager。在Fragment类中执行此操作不可能。
答案 7 :(得分:1)
如果以XML格式添加片段,则无法动态交换它们。他们过度地发生了什么,所以他们的事件并没有像人们期望的那样发射。这个问题记录了这个问题。 FragmenManager replace makes overlay
将middle_fragment转换为FrameLayout,然后像下面一样加载它,你的事件将被触发。
getFragmentManager().beginTransation().
add(R.id.middle_fragment, new MiddleFragment()).commit();
答案 8 :(得分:1)
你可以试试这个,
步骤1:覆盖活动中的Tabselected方法
Tableview
步骤2:使用静态方法在片段中执行您想要的操作,
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
try {
if(MyEventsFragment!=null && tab.getPosition()==3)
{
MyEvents.fragmentChanged();
}
}
catch (Exception e)
{
}
mViewPager.setCurrentItem(tab.getPosition());
}
答案 9 :(得分:1)
我在儿童片段中做了什么:
@Override
public void onDetach() {
super.onDetach();
ParentFragment pf = (ParentFragment) this.getParentFragment();
pf.onResume();
}
然后在ParentFragment上覆盖onResume
答案 10 :(得分:0)
对我来说,原因是使用 navGraph 在片段之间切换
app:navGraph
像这样(在 Kotlin 中)创建片段,然后调用所有生命周期函数
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.nav_host_fragment, fragment)
transaction.addToBackStack(null)
transaction.commit()
答案 11 :(得分:0)
我在活动中使用- KOTLIN
supportFragmentManager.addOnBackStackChangedListener {
val f = supportFragmentManager.findFragmentById(R.id.fragment_container)
if (f?.tag == "MyFragment")
{
//doSomething
}
}
答案 12 :(得分:0)
尽管使用不同的代码,但我遇到了与OP相同的问题,因为我最初使用
fm.beginTransaction()
.add(R.id.fragment_container_main, fragment)
.addToBackStack(null)
.commit();
代替
fm.beginTransaction()
.replace(R.id.fragment_container_main, fragment)
.addToBackStack(null)
.commit();
使用“ replace”,当您从第二个片段返回时,将重新创建第一个片段,因此也会调用onResume()。
答案 13 :(得分:0)
调用ft.replace
应该触发(替换片段的)onPause和(替换片段的)onResume。
我确实注意到您的代码在主片段上使login_fragment
膨胀,并且也没有在onCreateView中返回视图。如果这些是错别字,您能否说明在活动中如何调用这些片段?
答案 14 :(得分:0)
基于@Gor的答案,我在Kotlin中写了类似的文章。将此代码放在活动的onCreate()
中。它适用于一个可见的片段。如果您有ViewPager
的片段,它将调用ViewPager
的片段,而不是前一个片段。
supportFragmentManager.addOnBackStackChangedListener {
supportFragmentManager.fragments.lastOrNull()?.onResume()
}
阅读https://medium.com/@elye.project/puzzle-fragment-stack-pop-cause-issue-on-toolbar-8b947c5c07c6之后,我了解到在许多情况下,最好用replace
而不是add
附加新片段。因此,onResume
中的需求在某些情况下会消失。
答案 15 :(得分:0)
按照以下步骤操作,您将获得所需的答案
1-对于两个片段,创建一个新的抽象父片段
2-添加一个应由两者实现的自定义抽象方法
3-在更换第二个实例之前从当前实例调用它。
答案 16 :(得分:0)
data new_ops04;
set new_ops03;
array MONTHS (24) M1-M24;
AUXILIARY_COLUMN = 0;
do i=1 to 24;
IF MONTHS(i) ne 0 and AUXILIARY_COLUMN = 0 THEN
AUXILIARY_COLUMN = MONTHS(i);
end;
drop i;
run;
方法适用于您可以使用的活动类:
onPause()
出于同样的目的..
答案 17 :(得分:0)
片段必须始终嵌入到活动中,片段的生命周期直接受到主机活动生命周期的影响。例如,当活动暂停时,其中的所有片段也都会暂停,当活动被销毁时,所有片段也都会被删除
答案 18 :(得分:-2)
创建片段事务时,请确保添加以下代码。
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
还要确保在将事务添加到backstack后提交事务