Ric*_*cky 5 android android-fragments
我一直在试图弄清楚这一点,尽管阅读了很多书,但我肯定对片段在这里的工作方式有误解,或者我遇到了错误。
我有一个活动,其中包含一个FrameLayout.
创建活动时,我添加FragmentA.
if (savedInstanceState == null) {
Fragment newFragment = FragmentA.newInstance();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragment_container, newFragment, FRAGMENT_A_TAG).commit();
}
Run Code Online (Sandbox Code Playgroud)
FragmentA的onCreateOptionsMenu方法按照我的预期被调用(虽然,奇怪的onPrepareOptionsMenu是第一次被调用了两次?)。
FragmentA创建它自己的菜单,在这种情况下只是一个简单的菜单项。当菜单项被按下时,一个事件被触发回活动以创建FragmentB.
Fragment newFragment = FragmentB.newInstance();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragment_container, newFragment, FRAGMENT_B_TAG);
ft.addToBackStack(null);
ft.commit();
Run Code Online (Sandbox Code Playgroud)
现在问题来了。在这个阶段,我希望只调用FragmentB's onCreateOptionsMenu。但事实并非如此。FragmentA'sonCreateOptionsMenu被调用,然后是FragmentB's。
主要活动并没有任何相关的菜单中,只有片段。
为什么是这样?
如果我使用ft.replace(...),我没有这个问题。但这意味着每次弹出 FragmentB 时都要重新创建视图,我试图避免这种情况。
我希望这足以继续下去,但为了清楚起见,这里是活动的代码和两个片段。
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();
}
}
Run Code Online (Sandbox Code Playgroud)
小智 3
如果您致电:
ft.add(R.id.container, fragmentA, "tag").addToBackStack(null).commit();
Run Code Online (Sandbox Code Playgroud)
FragmentA 将保持“恢复”状态,并且其菜单将“膨胀”。那么如果你打电话:
ft.add(R.id.container, fragmentB, "tag").addToBackStack(null).commit();
Run Code Online (Sandbox Code Playgroud)
FragmentA 仍处于“已恢复”状态,现在 FragmentB 也处于“已恢复”状态,并且其菜单也将“膨胀”。
当您需要更新视图时,您应该使用 view.invalidate(),该方法将“重绘”视图。
我说过了...
如果你的MainActivity有菜单,它会调用invalidateOptionsMenu()来重绘MainActivity的菜单并绘制FragmentA的菜单。添加FragmentB后,工具栏需要添加其菜单,因此它将调用invalidateOptionsMenu()来重绘MainActivity和FragmentA菜单,并绘制FragmentB的菜单。这就是为什么每次更改 Fragment 时都会调用它,因为菜单视图需要重新绘制。
如果您使用,则不会发生这种情况
ft.replace(...)
Run Code Online (Sandbox Code Playgroud)
因为第一个 Fragment 将被销毁。
希望有助于理解。
记录您的 MainActivity 的 onCreateOptionsMenu ,并且每次添加具有菜单的片段时也会被调用。
| 归档时间: |
|
| 查看次数: |
1672 次 |
| 最近记录: |