I started writing an andoid app game but am already struggling with the navigation.
I have a Main Activity that is also the defaultNavHost of my navigation. It displays my Main Fragment, which has 3 buttons. Each should be leading to a different Fragment but that is where the problem occurs.
When clicking any of the buttons, I get the Error "MaterialButton [...] does not have a NavController set."
Example of one of the onClick() methods in my mainFragment:
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
view.findViewById(R.id.olympia_button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Navigation.findNavController(view).navigate(R.id.nav_main_to_olympia);
}
});
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:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
part of my nav_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/nav_graph"
app:startDestination="#id/mainFragment">
<fragment
android:id="#+id/mainFragment"
android:name="com.example.spieleolympiade.ui.main.MainFragment"
android:label="fragment_main"
tools:layout="#layout/fragment_main" >
<action
android:id="#+id/nav_main_to_olympia"
app:destination="#id/olympiaFragment" />
<action
android:id="#+id/nav_main_to_players"
app:destination="#id/playersFragment" />
<action
android:id="#+id/nav_main_to_halloffame"
app:destination="#id/hallOfFameFragment" />
</fragment>
<fragment
android:id="#+id/olympiaFragment"
android:name="com.example.spieleolympiade.ui.olympia.OlympiaFragment"
android:label="fragment_olympia"
tools:layout="#layout/fragment_olympia" >
<action
android:id="#+id/nav_olympia_to_main"
app:destination="#id/mainFragment" />
</fragment>
I have read online on posts such as this one that the official solution to this problem would be
NavHostFragment navHostFragment =
(NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
NavController navController = navHostFragment.getNavController();
now I don't understand:
I can't use the getSupportFragmentManager() function in my fragment where I need it
If i put that code in my mainActivity where I can use getSupportFragmentManager(), what do I then do with the navController variable that I get out of that.
Can you use below code for navigation from your fragment
NavHostFragment.findNavController(this).navigate(R.id. nav_main_to_olympia)
Related
When starting the app, I see neither the recycle view nor the normal fragment. I'm sure that the Navigation switch the fragments but I do not see results. But when I use the saveInstantState I can get the Recycle view to work but I can't switch fragments anymore...
Any help would be great.
Main.java
public class MainActivity extends AppCompatActivity {
MusicStoreService music;
private DrawerLayout drawerLayout;
private NavController navController;
private NavigationView navigationView;
private AppBarConfiguration appBarConfiguration;
public MainActivity() {
super(R.layout.main);
}
#Nullable
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
music = new MusicStoreServiceMock();
setContentView(R.layout.main);
Toolbar toolbar = findViewById(R.id.toolbar);
// make sure you import androidx.appcompat.widget.Toolbar !
setSupportActionBar(toolbar);
drawerLayout = findViewById(R.id.drawer_layout);
navigationView = findViewById(R.id.nav_view);
NavHostFragment navHostFragment = (NavHostFragment)
getSupportFragmentManager()
.findFragmentById(R.id.nav_host_fragment_container);
navController = navHostFragment.getNavController();
Set<Integer> topLevelDestinations = new HashSet<>();
topLevelDestinations.add(R.id.productListFragment2);
topLevelDestinations.add(R.id.helloworld);
appBarConfiguration = new AppBarConfiguration.Builder(topLevelDestinations)
.setOpenableLayout(drawerLayout)
.build();
NavigationUI.setupWithNavController(toolbar, navController,
appBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.setReorderingAllowed(true)
.add(R.id.nav_host_fragment_container, ProductListFragment.class, null)
.commit();
System.out.println();
}
}
public MusicStoreService getMusic() {
return music;
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<androidx.coordinatorlayout.widget.CoordinatorLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_scrollFlags="scroll|enterAlways" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_fragment_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph" />
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:menu="#menu/nav_menu"
/>
<!-- attribute app:menu isn't mentioned in the documentation! -->
</androidx.drawerlayout.widget.DrawerLayout>
menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item android:title="MusicStore">
<menu>
<item
android:id="#+id/productListFragment2"
android:title="Products" />
</menu>
</item>
<item android:title="Service">
<menu>
<item
android:id="#+id/helloworld"
android:title="Your Account" />
</menu>
</item>
</group>
</menu>
nav_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/nav_graph"
app:startDestination="#id/productListFragment2">
<fragment
android:id="#+id/productListFragment2"
android:name="musicstore.fragments.ProductListFragment"
android:label="Product List" >
<action
android:id="#+id/action_productListFragment2_to_mainActivity2"
app:destination="#id/mainActivity2" />
</fragment>
<fragment
android:id="#+id/helloworld"
android:name=".musicstore.fragments.helloworld"
android:label="Your Account"
tools:layout="#layout/fragment_helloworld" />
<fragment
android:id="#+id/productDetailFragment2"
android:name="musicstore.fragments.ProductDetailFragment"
android:label="ProductDetailFragment" />
<activity
android:id="#+id/mainActivity2"
android:name="musicstore.MainActivity"
android:label="activity_main"
tools:layout="#layout/activity_main" />
</navigation>
Recycle view fragment:
public class ProductListFragment extends Fragment {
RecyclerView recyclerView;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
System.out.println("Hello");
View v = inflater.inflate(R.layout.product_list_fragment, container, false);
recyclerView = (RecyclerView) v.findViewById(R.id.productlist_recycler);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
return v;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
ProductListAdapter pld = new ProductListAdapter(((MainActivity) getActivity()).getMusic(),getContext(),new ClickerListener());
recyclerView.setAdapter(pld);
}
Simple fragment:
public class helloworld extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_helloworld, container, false);
}
}
I'm looking for the following design in my android app:
I want the main screen to be a TabLayout with 3 tabs, and a ViewPager2.
From each one of the 3 fragments (Fragment1, Fragment2, Fragment3) corresponding to the tabs, there are some actions the user can do to navigate to other fragments--those don't have the TabLayout and ViewPager2. Those nav actions are handled by a nav_graph.
Currently, this is what I'm working with:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="#+id/main_activity_coordinator"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
app:layout_constraintTop_toTopOf="parent"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:id="#+id/app_bar"
>
<!-- toolbar -->
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:tag="MAIN-FRAG"
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="70dp"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
main_fragment.xml (this contains the TabLayout and ViewPager2)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:tag="MAIN-FRAG"
android:id="#+id/main_relative_layout"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:paddingTop="?attr/actionBarSize"
xmlns:tools="http://schemas.android.com/tools">
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<com.google.android.material.tabs.TabItem
...
/>
<com.google.android.material.tabs.TabItem
...
/>
<com.google.android.material.tabs.TabItem
...
/>
</com.google.android.material.tabs.TabLayout>
<androidx.viewpager2.widget.ViewPager2
android:layout_below="#id/tabBar"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
/>
</RelativeLayout>
MainFragment.java
public class MainFragment extends Fragment {
private ViewPager2 viewPager;
private NavigationAdapter navigationAdapter;
private MainFragmentBinding binding;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setContentView(R.layout.main_fragment);
TabLayout tabLayout = getActivity().findViewById(R.id.tabBar);
int[] tabTexts = {
R.string.tab1,
R.string.tab2,
R.string.tab3
};
// set up view pager and attach mediator to tab layout
this.viewPager = getActivity().findViewById(R.id.pager);
this.navigationAdapter = new NavigationAdapter(this);
viewPager.setAdapter(this.navigationAdapter);
new TabLayoutMediator(tabLayout, viewPager,
(tab, position) -> tab.setText(
tabTexts[position]
)
).attach();
}
}
nav_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/nav_graph"
app:startDestination="#id/Fragment1">
<fragment
android:id="#+id/Fragment1"
android:name="com.my_app..fragments.MainFragment"
tools:layout="#layout/main_fragment">
<action
android:id="#+id/action_Fragment1_to_FragmentX"
app:destination="#id/FragmentX" />
</fragment>
<fragment
android:id="#+id/FragmentX"
android:name="com.my_app.fragments.FragmentX"
tools:layout="#layout/fragment_x">
</fragment>
<fragment
android:id="#+id/Fragment2"
android:name="com.my_app.fragments.ExercisesFragment"
tools:layout="#layout/fragment_2">
<action
android:id="#+id/action_Fragment2_to_FragmentY"
app:destination="#id/FragmentY" />
</fragment>
<fragment
android:id="#+id/FragmentY"
android:name="com.my_app.fragments.ExerciseDetailFragment"
tools:layout="#layout/fragment_y">
</fragment>
</navigation>
In other words, the TabLayout handles Fragment1, Fragment2, and Fragment3 (not shown in the nav graph because it doesn't have outward actions). From Fragment1, you can navigate to FragmentX (which doesn't not have the tablayout) and from Fragment2 to FragmentY.
This seems to be working, but if I rotate my screen I get the following error:
2022-05-06 11:09:00.009 11445-11445/com.my_app E/FragmentManager: Fragment no longer exists for key f#0: unique id ba9898fb-18f8-4eaa-a250-97c08a896379
2022-05-06 11:09:00.009 11445-11445/com.my_app E/FragmentManager: Activity state:
2022-05-06 11:09:00.031 11445-11445/com.my_app E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.my_app, PID: 11445
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.my_app/com.my_app.MainActivity}: java.lang.IllegalStateException: Fragment no longer exists for key f#0: unique id ba9898fb-18f8-4eaa-a250-97c08a896379
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2827)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2902)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4784)
at android.app.ActivityThread.-wrap18(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1609)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:169)
at android.app.ActivityThread.main(ActivityThread.java:6578)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.IllegalStateException: Fragment no longer exists for key f#0: unique id ba9898fb-18f8-4eaa-a250-97c08a896379
at androidx.fragment.app.FragmentManager.getFragment(FragmentManager.java:975)
at androidx.viewpager2.adapter.FragmentStateAdapter.restoreState(FragmentStateAdapter.java:549)
at androidx.viewpager2.widget.ViewPager2.restorePendingState(ViewPager2.java:350)
at androidx.viewpager2.widget.ViewPager2.dispatchRestoreInstanceState(ViewPager2.java:375)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3729)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3729)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3729)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3729)
at android.view.View.restoreHierarchyState(View.java:17620)
at com.android.internal.policy.PhoneWindow.restoreHierarchyState(PhoneWindow.java:2130)
at android.app.Activity.onRestoreInstanceState(Activity.java:1122)
at android.app.Activity.performRestoreInstanceState(Activity.java:1077)
I believe this is somehow tied to the fact that my nav_graph uses one of the fragments managed by the ViewPager2 as its start destination. However, if I try and use the MainFragment as my start destination, then I can't navigate to FragmentX and FragmentY, because if I do, I'll get an error saying the action isn't valid when I'm in MainFragment.
How can I use both ViewPager2 and NavGraph correctly?
I created custom toolbar inside fragment,but i got view like this:
In themes.xml i disabled ActionBar:
<style name="Theme.Project" parent="Theme.MaterialComponents.DayNight.NoActionBar">
This is my custom toolbar layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/white"
>
<TextView
android:id="#+id/toolbar_title"
style="#style/TextAppearance.AppCompat.Widget.ActionBar.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Home"
android:fontFamily="#font/google_sans"
android:textColor="#color/black"
android:textSize="20sp" />
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<include layout="#layout/fragment_home" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
And this is HomeFragment.java:
public class HomeFragment extends Fragment {
private HomeViewModel homeViewModel;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
homeViewModel =
new ViewModelProvider(this).get(HomeViewModel.class);
View root = inflater.inflate(R.layout.toolbar_in_home, container, false);
return root;
}
}
How to remove this white thing on top of screen?
UPD:
<?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=".ui.home.HomeFragment">
</androidx.constraintlayout.widget.ConstraintLayout>
This is fragment home(just ConstraintLayout)
UPD2:i also was trying use toolbar in activity_main and it works:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.toolbar);
BottomNavigationView navView = findViewById(R.id.nav_view);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home, R.id.navigation_examination, R.id.navigation_profile)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupWithNavController(navView, navController);
}
But i can't do changes if i want to go on other fragment.
I need to set another custom toolbar layout with button like this:
So this is how I did it. My app is based on single activity-multi-fragment model.
I had set activity theme to AppTheme.NoActionBar, so it enabled me to set a custom toolbar.
Later for each fragment I had a separate layout and within which added a custom toolbar like below
<androidx.appcompat.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/colorPrimary">
....
....
</androidx.appcompat.widget.Toolbar>
Within this layout I had added menu items.
If you don't want to follow this, may be you should look at getActionBar().setCustomView(). Keep your activity theme set, so getActionBar() is not null.
You can control action bar layout by calling getActionBar().setCustomView() in fragment onResume() or probably when you are adding or removing a fragment in your activity.
You can use your custom toolbar inside the main layout replace it from com.google.android.material.appbar.AppBarLayout.
Here is an example code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_alignParentTop="true"
android:layout_centerInParent="true"
android:background="#color/colorPrimary">
<ImageView
android:id="#+id/navi"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentStart="true"
android:layout_centerInParent="true"
android:layout_marginStart="20dp"
android:contentDescription="#string/todo"
android:src="#drawable/navi" />
<ImageView
android:layout_width="180dp"
android:layout_height="?attr/actionBarSize"
android:layout_alignParentTop="true"
android:layout_centerInParent="true"
android:contentDescription="#string/todo"
android:src="#drawable/header2" />
</RelativeLayout>
<include layout="#layout/fragment_home" />
</RelativeLayout>
I added navigation drawer on map activity. Now I'm trying to add a fragment on my home activity, but fragment is not showing in activity, but code in fragment class is working.
Is my FrameLayout hiding behind the map fragment?
I'm very new to fragments.
Please help me.
Home class layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/constrain_layout"
android:orientation="vertical">
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="0dp"
map:layout_constraintBottom_toBottomOf="parent"
map:layout_constraintEnd_toEndOf="parent"
map:layout_constraintStart_toStartOf="parent"
map:layout_constraintTop_toTopOf="parent" />
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:layout_constraintBottom_toBottomOf="parent"
map:layout_constraintEnd_toEndOf="parent"
map:layout_constraintHorizontal_bias="0.0"
map:layout_constraintStart_toStartOf="parent"
map:layout_constraintTop_toTopOf="parent"
map:layout_constraintVertical_bias="0.0"
tools:context=".HomeActivity" />
</androidx.constraintlayout.widget.ConstraintLayout>
Fragment class
public class RideHistory extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
Toast.makeText(getActivity(), "Ride History", Toast.LENGTH_SHORT).show();
View view = inflater.inflate(R.layout.fragment_ride_history,container,false);
return view;
}
}
Fragment 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragments.RideHistory">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Ride History" />
</FrameLayout>
Change layout constraints so that both widgets frame layout and map fragment do not overlap eachother.
for ex:
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
map:layout_constraintBottom_toTopOf="#+id/map"
map:layout_constraintEnd_toEndOf="parent"
map:layout_constraintStart_toStartOf="parent"
map:layout_constraintTop_toTopOf="parent" />
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="434dp"
android:layout_height="297dp"
map:layout_constraintBottom_toBottomOf="parent"
map:layout_constraintEnd_toEndOf="parent"
map:layout_constraintHorizontal_bias="0.0"
map:layout_constraintStart_toStartOf="parent"
tools:context=".HomeActivity" />
I'm unable to find any examples using java, all the codelabs given by google seem to be in kotlin and ideally i don't want to learn that language.
Is there any simple example of using 1 activity, 2/3 fragments all linked in by the bottom navigation bar that I can browse for?
I've looked at all the documentation provided by google and unable to make any sense of it.
All I do know is that i am expected to use
NavHostFragment.findNavController(Fragment)
Navigation.findNavController(Activity, #IdRes int viewId)
Navigation.findNavController(View)
And that in java i should be using
Navigation.createNavigateOnClickListener()
I am hoping i am not too far off with this:
public class MainActivity extends AppCompatActivity {
NavController navController;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView navView = findViewById(R.id.nav_view);
navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupWithNavController(navView,navController);
}
}
Thanks.
Eventually found the answer, for anyone else who is facing similar newbie issues:
/res/layout/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:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<fragment
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="#navigation/nav_graph"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/nav_view"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
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>
MainActivity.java under onCreate
BottomNavigationView navView = findViewById(R.id.nav_view);
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupWithNavController(navView,navController);
Under /res/navigation/nav_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/nav_graph"
app:startDestination="#id/mapFragment">
<fragment
android:id="#+id/mapFragment"
android:name="com.company.pinpoint.MapFragment"
android:label="fragment_map"
tools:layout="#layout/fragment_map">
<action
android:id="#+id/action_mapFragment_to_newsFeedFragment"
app:destination="#id/newsFeedFragment" />
<!--app:enterAnim="#anim/slide_in_right"-->
<!--app:exitAnim="#anim/slide_out_left"-->
<!--app:popEnterAnim="#anim/slide_in_left"-->
<!--app:popExitAnim="#anim/slide_out_right" />-->
</fragment>
<fragment
android:id="#+id/newsFeedFragment"
android:name="com.company.pinpoint.NewsFeedFragment"
android:label="fragment_news_feed"
tools:layout="#layout/fragment_news_feed" />
</navigation>