对话框关闭时如何切换现有片段?
How to switch existing fragments when the dialog is closed?
应用程序的主屏幕适用于 bottom navigation
。
并且有3个菜单,都是fragments
.
按下其中一个片段上的按钮可打开 dialog fragment
window。
并且当对话框关闭时,旧片段应该切换到另一个新片段。
我使用 show()
和 hide()
而不是 replace()
。
MainAcitivity.java
public class MainActivity extends AppCompatActivity {
BottomNavigationView bottomNav;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bottomNav = findViewById(R.id.bottom_nav);
bottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
Fragment curFrag = fm.getPrimaryNavigationFragment();
String tag = String.valueOf(item.getItemId());
int id = item.getItemId();
if(curFrag != null) {
transaction.hide(curFrag);
}
Fragment fragment = fm.findFragmentByTag(tag);
if(fragment == null) {
if(id == R.id.list)
fragment = new WorkoutListFragment();
transaction.add(R.id.content_layout, fragment);
}
else {
transaction.show(fragment);
}
transaction.setPrimaryNavigationFragment(fragment);
transaction.setReorderingAllowed(true);
transaction.commitNow();
return true;
}
});
}
// Switch to another fragment when the dialog is closed
public void onFragmentChanged() {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
String tag = "ABC";
Fragment currentFragment = fragmentManager.getPrimaryNavigationFragment();
if (currentFragment != null) {
fragmentTransaction.hide(currentFragment);
}
Fragment fragment = fragmentManager.findFragmentByTag(tag);
if (fragment == null) {
fragment = new WriteRoutineFragment();
fragmentTransaction.add(R.id.container, fragment, tag);
} else {
fragmentTransaction.show(fragment);
}
fragmentTransaction.setPrimaryNavigationFragment(fragment);
fragmentTransaction.setReorderingAllowed(true);
fragmentTransaction.commitNow();
}
}
DialogFragment.java
Button startBtn;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_body_part_dialog, null);
startBtn = view.findViewById(R.id.check);
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MainActivity activity = (MainActivity) getActivity();
activity.onFragmentChanged(); // change fragment
dismiss();
}
});
return view;
}
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.setCanceledOnTouchOutside(false);
return dialog;
}
}
WriteRoutineFragment.java
public class WriteRoutineFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_write_routine, container, false);
return rootView;
}
}
错误
java.lang.IllegalArgumentException: No view found for id 0x7f0a0082 (com.example.writeweight:id/container) for fragment WriteRoutineFragment{f3a9b6 (137e8e27-12af-4e5a-9397-2cbdc80ed980) id=0x7f0a0082 ABC}
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:875)
at androidx.fragment.app.FragmentManagerImpl.addAddedFragments(FragmentManagerImpl.java:2100)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1874)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1830)
at androidx.fragment.app.FragmentManagerImpl.execSingleAction(FragmentManagerImpl.java:1696)
at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:293)
at com.example.writeweight.activity.MainActivity.onFragmentChanged(MainActivity.java:78)
at com.example.writeweight.fragment.BodyPartDialogFragment.onClick(BodyPartDialogFragment.java:89)
at android.view.View.performClick(View.java:8160)
at android.widget.TextView.performClick(TextView.java:16221)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:992)
at android.view.View.performClickInternal(View.java:8137)
at android.view.View.access00(View.java:888)
at android.view.View$PerformClick.run(View.java:30236)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:246)
at android.app.ActivityThread.main(ActivityThread.java:8506)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
I/Process: Sending signal. PID: 23516 SIG: 9
已添加
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.MainActivity">
<FrameLayout
android:id="@+id/content_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/bottom_nav"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu"/>
</androidx.constraintlayout.widget.ConstraintLayout>
fragment_write_routine.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragment.WriteRoutineFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
当你说
fragmentTransaction.add(R.id.container, fragment, tag);
您的意思是您希望 FragmentManager 在您的布局中找到 R.id.container
并将您的片段添加到该容器中。当您使用 getSupportFragmentManager()
时,您正在使用 Activity 的 FragmentManager,因此,R.id.container
需要在您的 activity 布局中。但是,R.id.container
不在您的 activity 布局中,这就是您遇到异常的原因。
相反,您应该在 Activity 的布局中使用 是 的容器 - R.id.content_layout
:
fragmentTransaction.add(R.id.content_layout, fragment, tag);
应用程序的主屏幕适用于 bottom navigation
。
并且有3个菜单,都是fragments
.
按下其中一个片段上的按钮可打开 dialog fragment
window。
并且当对话框关闭时,旧片段应该切换到另一个新片段。
我使用 show()
和 hide()
而不是 replace()
。
MainAcitivity.java
public class MainActivity extends AppCompatActivity {
BottomNavigationView bottomNav;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bottomNav = findViewById(R.id.bottom_nav);
bottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
Fragment curFrag = fm.getPrimaryNavigationFragment();
String tag = String.valueOf(item.getItemId());
int id = item.getItemId();
if(curFrag != null) {
transaction.hide(curFrag);
}
Fragment fragment = fm.findFragmentByTag(tag);
if(fragment == null) {
if(id == R.id.list)
fragment = new WorkoutListFragment();
transaction.add(R.id.content_layout, fragment);
}
else {
transaction.show(fragment);
}
transaction.setPrimaryNavigationFragment(fragment);
transaction.setReorderingAllowed(true);
transaction.commitNow();
return true;
}
});
}
// Switch to another fragment when the dialog is closed
public void onFragmentChanged() {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
String tag = "ABC";
Fragment currentFragment = fragmentManager.getPrimaryNavigationFragment();
if (currentFragment != null) {
fragmentTransaction.hide(currentFragment);
}
Fragment fragment = fragmentManager.findFragmentByTag(tag);
if (fragment == null) {
fragment = new WriteRoutineFragment();
fragmentTransaction.add(R.id.container, fragment, tag);
} else {
fragmentTransaction.show(fragment);
}
fragmentTransaction.setPrimaryNavigationFragment(fragment);
fragmentTransaction.setReorderingAllowed(true);
fragmentTransaction.commitNow();
}
}
DialogFragment.java
Button startBtn;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_body_part_dialog, null);
startBtn = view.findViewById(R.id.check);
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MainActivity activity = (MainActivity) getActivity();
activity.onFragmentChanged(); // change fragment
dismiss();
}
});
return view;
}
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.setCanceledOnTouchOutside(false);
return dialog;
}
}
WriteRoutineFragment.java
public class WriteRoutineFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_write_routine, container, false);
return rootView;
}
}
错误
java.lang.IllegalArgumentException: No view found for id 0x7f0a0082 (com.example.writeweight:id/container) for fragment WriteRoutineFragment{f3a9b6 (137e8e27-12af-4e5a-9397-2cbdc80ed980) id=0x7f0a0082 ABC}
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:875)
at androidx.fragment.app.FragmentManagerImpl.addAddedFragments(FragmentManagerImpl.java:2100)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1874)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1830)
at androidx.fragment.app.FragmentManagerImpl.execSingleAction(FragmentManagerImpl.java:1696)
at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:293)
at com.example.writeweight.activity.MainActivity.onFragmentChanged(MainActivity.java:78)
at com.example.writeweight.fragment.BodyPartDialogFragment.onClick(BodyPartDialogFragment.java:89)
at android.view.View.performClick(View.java:8160)
at android.widget.TextView.performClick(TextView.java:16221)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:992)
at android.view.View.performClickInternal(View.java:8137)
at android.view.View.access00(View.java:888)
at android.view.View$PerformClick.run(View.java:30236)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:246)
at android.app.ActivityThread.main(ActivityThread.java:8506)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
I/Process: Sending signal. PID: 23516 SIG: 9
已添加
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.MainActivity">
<FrameLayout
android:id="@+id/content_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/bottom_nav"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu"/>
</androidx.constraintlayout.widget.ConstraintLayout>
fragment_write_routine.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragment.WriteRoutineFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
当你说
fragmentTransaction.add(R.id.container, fragment, tag);
您的意思是您希望 FragmentManager 在您的布局中找到 R.id.container
并将您的片段添加到该容器中。当您使用 getSupportFragmentManager()
时,您正在使用 Activity 的 FragmentManager,因此,R.id.container
需要在您的 activity 布局中。但是,R.id.container
不在您的 activity 布局中,这就是您遇到异常的原因。
相反,您应该在 Activity 的布局中使用 是 的容器 - R.id.content_layout
:
fragmentTransaction.add(R.id.content_layout, fragment, tag);