gpt4 book ai didi

android - 为什么使用 FragmentTransaction add() 方法在每个 fragment 中调用 onCreateOptionsMenu()?

转载 作者:搜寻专家 更新时间:2023-11-01 09:40:48 29 4
gpt4 key购买 nike

我一直在努力解决这个问题,尽管阅读了大量书籍,但我一定对 fragment 在这里的工作方式有误解,或者我遇到了错误。

我有一个 Activity ,其中包含一个 FrameLayout

创建 Activity 时,我添加了 FragmentA

    if (savedInstanceState == null) {            
Fragment newFragment = FragmentA.newInstance();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragment_container, newFragment, FRAGMENT_A_TAG).commit();
}

FragmentAonCreateOptionsMenu 方法如我所料被调用(尽管奇怪的是 onPrepareOptionsMenu 第一次被调用了两次?)。

FragmentA 创建自己的菜单,在本例中只是一个简单的菜单项。当按下菜单项时,一个事件将被触发回 Activity 以创建 FragmentB

    Fragment newFragment = FragmentB.newInstance();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragment_container, newFragment, FRAGMENT_B_TAG);
ft.addToBackStack(null);
ft.commit();

问题来了。在这个阶段,我希望只有 FragmentBonCreateOptionsMenu 被调用。但事实并非如此。 FragmentAonCreateOptionsMenu 被调用,然后是 FragmentB 的。

主要 Activity 没有有任何关联的菜单,只有 fragment 。

这是为什么?

如果我使用 ft.replace(...),我就没有这个问题。但这意味着每次弹出 FragmentB 时都要重新创建 View ,我正在努力避免这种情况。

我希望这足以继续下去,但为了清楚起见,这里是 Activity 的代码和两个 fragment 。

public class MainActivity extends AppCompatActivity {

private static String FRAGMENT_A_TAG = "FRAGMENT_A_TAG";
private static String FRAGMENT_B_TAG = "FRAGMENT_B_TAG";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);

// Watch for button clicks.
Button button = (Button) findViewById(R.id.btn_switch_fragment);

button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
addFragmentToStack();
}
});

if (savedInstanceState == null) {
// Do first time initialization -- add initial fragment.
Fragment newFragment = FragmentA.newInstance();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragment_container, newFragment, FRAGMENT_A_TAG).commit();
}
}

private void addFragmentToStack() {

Fragment newFragment = FragmentB.newInstance();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragment_container, newFragment, FRAGMENT_B_TAG);
ft.addToBackStack(null);
ft.commit();
}


}

public class FragmentA extends Fragment {

public FragmentA() {
// Required empty public constructor
}

public static FragmentA newInstance() {
FragmentA fragment = new FragmentA();
return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setHasOptionsMenu(true);

System.out.println("onCreate called");
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {

System.out.println("onCreateView called");

// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_a, container, false);
}



@Override
public void onPrepareOptionsMenu(Menu menu) {

System.out.println("onPrepareOptionsMenu called");

super.onPrepareOptionsMenu(menu);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_example_a, menu);
}

@Override
public void onAttach(Context context) {
super.onAttach(context);

}

@Override
public void onDetach() {
super.onDetach();

}

@Override
public void onResume() {
super.onResume();

System.out.println("onResume called");
}
}

public class FragmentB extends Fragment {

public FragmentB() {
// Required empty public constructor
}

public static FragmentB newInstance() {
FragmentB fragment = new FragmentB();
return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setHasOptionsMenu(true);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_b, container, false);
}

@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_example_b, menu);
}

@Override
public void onAttach(Context context) {
super.onAttach(context);

}

@Override
public void onDetach() {
super.onDetach();

}

}

最佳答案

如果你调用:

ft.add(R.id.container, fragmentA, "tag").addToBackStack(null).commit();

FragmentA 将保持“恢复”状态,其菜单将“膨胀”。那么如果你调用:

ft.add(R.id.container, fragmentB, "tag").addToBackStack(null).commit();

FragmentA 仍在“恢复”,现在 FragmentB 也处于状态“恢复”,其菜单也将“膨胀”。

When you need to update a view you should use view.invalidate(), and this method will "redraw" the view.

这么说...

如果您的 MainActivity 有一个菜单,它将调用 invalidateOptionsMenu() 来重绘 MainActivity 的菜单并绘制 FragmentA 的菜单。添加FragmentB后工具栏需要添加菜单,所以会调用invalidateOptionsMenu()重绘MainActivity和FragmentA的菜单,同时绘制FragmentB的菜单。这就是每次更改 Fragment 时都会调用它的原因,因为需要重绘菜单 View 。

如果你使用

就不会发生这种情况
ft.replace(...)

因为第一个Fragment会被销毁。

希望对理解有所帮助。


记录您的 MainActivity 的 onCreateOptionsMenu 并且在您每次添加具有菜单的 Fragment 时也会被调用。

关于android - 为什么使用 FragmentTransaction add() 方法在每个 fragment 中调用 onCreateOptionsMenu()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39975096/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com