The main screen of the app is for bottom navigation
.
And there are 3 menus, all of which are fragments
.
Pressing the button on one of the fragments opens the dialog fragment
window.
And when the dialog is closed, the old fragment should be switched to another new fragment.
I use show()
and hide()
instead of 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;
}
}
ERROR
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$2.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.access$3700(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
ADDED
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>
When you say
fragmentTransaction.add(R.id.container, fragment, tag);
What you're saying is that you want the FragmentManager to find the R.id.container
in your layout and add your fragment to that container. As you're using getSupportFragmentManager()
, you're using the Activity's FragmentManager and hence, R.id.container
needs to be in your activity's layout. However, R.id.container
isn't in your activity's layout, which is why you're getting an exception.
Instead, you should be using the container that is in your Activity's layout - R.id.content_layout
:
fragmentTransaction.add(R.id.content_layout, fragment, tag);