I implement a single-activity architecture with flow fragments in Java. My MainFlowFragment
is where I setup bottom navigation view with 4 fragments inside this flow.
MainFlowFragment.java:
package kz.rating.onaikazakh.presentation.ui.fragments.mainflow;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.NavGraph;
import androidx.navigation.Navigation;
import androidx.navigation.fragment.NavHostFragment;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import kz.rating.onaikazakh.R;
import kz.rating.onaikazakh.databinding.FlowFragmentMainBinding;
public class MainFlowFragment extends Fragment {
private NavController navController=null;
private FlowFragmentMainBinding binding;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.flow_fragment_main, container, false);
return view;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
/*Fragment navHostFragment = getChildFragmentManager().findFragmentById(R.id.nav_host_fragment_main);
navController = Navigation.findNavController(navHostFragment, R.id.nav_host_fragment_main);*/
BottomNavigationView bnv = view.findViewById(R.id.bottom_navigation);
NavHostFragment navHostFragment = (NavHostFragment) getChildFragmentManager().findFragmentById(R.id.nav_host_fragment_main);
navController = navHostFragment.getNavController();
NavGraph navGraph = navController.getNavInflater().inflate(R.navigation.main_graph);
/*AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_grammar, R.id.navigation_texts, R.id.navigation_vocabulary, R.id.navigation_profile)
.build();
NavigationUI.setupActionBarWithNavController((AppCompatActivity)getActivity(), navController, appBarConfiguration);
NavigationUI.setupWithNavController(bnv, navController);*/
bnv.setupWithNavController(navController);
navController.setGraph(navGraph);
}
@Override
public void onDestroyView() {
super.onDestroyView();
}
}
flow_fragment_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"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/wave_imageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitXY"
app:srcCompat="@drawable/wave" />
</RelativeLayout>
<FrameLayout
android:id="@+id/container_test"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:layout_marginTop="@dimen/activity_top_margin"
android:fitsSystemWindows="true"
app:layout_constraintBottom_toTopOf="@id/bottom_navigation"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:navGraph="@navigation/main_graph" />
</FrameLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:menu="@menu/bottom_nav_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
bottom_nav_menu.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_grammar"
android:icon="@drawable/grammar_nav_icon"
android:title="@string/title_grammar" />
<item
android:id="@+id/navigation_texts"
android:icon="@drawable/texts_nav_icon"
android:title="@string/title_texts" />
<item
android:id="@+id/navigation_vocabulary"
android:icon="@drawable/vocab_nav_icon"
android:title="@string/title_vocabulary" />
<item
android:id="@+id/navigation_profile"
android:icon="@drawable/profile_nav_icon"
android:title="@string/title_profile" />
</menu>
main_graph.xml:
<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/mobile_navigation"
app:startDestination="@+id/navigation_grammar">
<fragment
android:id="@+id/navigation_grammar"
android:name="kz.rating.onaikazakh.presentation.ui.fragments.mainflow.grammar.GrammarFragment"
android:label="@string/title_grammar"
tools:layout="@layout/fragment_show_material_list" />
<fragment
android:id="@+id/navigation_texts"
android:name="kz.rating.onaikazakh.presentation.ui.fragments.mainflow.texts.TextsFragment"
android:label="@string/title_texts"
tools:layout="@layout/fragment_show_material_list" />
<fragment
android:id="@+id/navigation_vocabulary"
android:name="kz.rating.onaikazakh.presentation.ui.fragments.mainflow.vocabulary.VocabularyFragment"
android:label="@string/title_vocabulary"
tools:layout="@layout/fragment_vocabulary" />
<fragment
android:id="@+id/navigation_profile"
android:name="kz.rating.onaikazakh.presentation.ui.fragments.mainflow.profile.ProfileFragment"
android:label="@string/title_profile"
tools:layout="@layout/fragment_profile" />
</navigation>
App level build.gradle:
apply plugin: 'com.android.application'
apply plugin: 'androidx.navigation.safeargs'
android {
compileSdkVersion 31
buildToolsVersion "30.0.2"
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
checkReleaseBuilds false
}
defaultConfig {
applicationId "kz.rating.onaikazakh"
minSdkVersion 23
targetSdkVersion 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
buildFeatures {
viewBinding = true
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.6.0'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
def nav_version = "2.5.3"
// Java language implementation
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"
// Kotlin
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
// Feature module Support
implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"
// Testing Navigation
androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"
// Jetpack Compose Integration
implementation "androidx.navigation:navigation-compose:$nav_version"
}
Project build.gradle:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.1"
def nav_version = "2.5.3"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
android.useAndroidX=true
is set in gradle.properties
What I have tried:
I saw this post and tried both in onCreateView and onViewCreated. I tried to update all dependencies to the latest versions, and also to the versions from other answers on the topic. I tried Invalidate Cache. None of these worked.
I also tried setting up with NavigationUI.setupWithNavController(bnv, navController). In this case, it shows the bottomNavView and main flow, however no fragments are inflated.
Does anyone know how to fix that? Or is there another way to bind navController to bottomNavView within a flow fragment in Java?
Update
Thanks to Sohaib Ahmed, it worked with NavigationUI.setupWithNavController. I forgot changing properties after moving the block from Constraint to Frame layout. However, the original question is still relevant, so it would be beneficial if anyone knows why this error occurs.
Change your height to match_parent
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:navGraph="@navigation/main_graph" />
to
android:layout_height="match_parent"