11

I have a fragment A where an action is originated to fragment B which have to receive an argument. When I try to set the argument before navigate, 'FragmentADirections' class can't be resolve. The fact is, I have a fragment C going to D with an argument to and this work well for these two.

Fragment A class ('EntrainementAction'):

    package com.example.androidsportsomveille.Fragments;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;

import com.example.androidsportsomveille.Classes.Entrainement;
import com.example.androidsportsomveille.R;

public class EntrainementAction extends Fragment {

    private Entrainement entrainement;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_entrainement_action, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        this.entrainement = EntrainementActionArgs.fromBundle(getArguments()).getMyEntrainement();

        // Remplis le layout avec les données de l'enrainement
        populateLayout();

        // Aller à la gestion de l'entrainement
        Button btnGestion = view.findViewById(R.id.btnGestionEntrainement);
        btnGestion.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Set de l'argument puis navigation
                EntrainementActionDirections.ActionEntrainementActionToEntrainementGestion action =
                        EntrainementActionDirections.actionEntrainementActionToEntrainementGestion(entrainement);
                Navigation.findNavController(view).navigate(action);
            }
        });
    }

    public void populateLayout() {
        TextView txtNom = getView().findViewById(R.id.txtNomEntrainement);
        txtNom.setText(this.entrainement.getNom());
    }
}

Error appear in 'btnGestion.setOnClickListener' where 'EntrainementActionDirections' cannot be resolve. Note that I have other Directions class well generated.

My nav_graph.xml file:

<?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/entrainementListe">

    <fragment
        android:id="@+id/entrainementListe"
        android:name="com.example.androidsportsomveille.Fragments.EntrainementListe"
        android:label="fragment_entrainement_liste"
        tools:layout="@layout/fragment_entrainement_liste" >
        <action
            android:id="@+id/action_entrainementListe_to_entrainementNouveau"
            app:destination="@id/entrainementNouveau" />
        <action
            android:id="@+id/action_entrainementListe_to_entrainementAction"
            app:destination="@id/entrainementAction" />
    </fragment>

    <fragment
        android:id="@+id/entrainementNouveau"
        android:name="com.example.androidsportsomveille.Fragments.EntrainementNouveau"
        android:label="fragment_entrainement_nouveau"
        tools:layout="@layout/fragment_entrainement_nouveau" >
        <action
            android:id="@+id/action_entrainementNouveau_to_entrainementGestion"
            app:destination="@id/entrainementGestion" />
    </fragment>
    <fragment
        android:id="@+id/entrainementAction"
        android:name="com.example.androidsportsomveille.Fragments.EntrainementAction"
        android:label="fragment_entrainement_action"
        tools:layout="@layout/fragment_entrainement_action" >
        <argument
            android:name="myEntrainement"
            app:argType="com.example.androidsportsomveille.Classes.Entrainement" />
        <action
            android:id="@+id/action_entrainementAction_to_entrainementGestion"
            app:destination="@id/entrainementGestion" />
    </fragment>
    <fragment
        android:id="@+id/entrainementGestion"
        android:name="com.example.androidsportsomveille.Fragments.EntrainementGestion"
        android:label="fragment_entrainement_gestion"
        tools:layout="@layout/fragment_entrainement_gestion" >
        <action
            android:id="@+id/action_entrainementGestion_to_entrainementAction"
            app:destination="@id/entrainementAction" />
        <argument
            android:name="myEntrainement"
            app:argType="com.example.androidsportsomveille.Classes.Entrainement" />
    </fragment>
</navigation>

Fragments 'entrainementAction' and 'entrainementGestion' haven't Directions class generated while 'entrainementListe' and 'entrainementNouveau' have. All fragment's xml files exists.

Bolt UIX
  • 5,988
  • 6
  • 31
  • 58
Skunka
  • 525
  • 2
  • 6
  • 22

3 Answers3

21

double-check to have this in your app Gradle (at top)

plugins {
    id "androidx.navigation.safeargs.kotlin"
}
Vahab Ghadiri
  • 2,016
  • 20
  • 26
  • only buildscript {} and other plugins {} script blocks are allowed before plugins {} blocks, no other statements are allowed – behelit Aug 23 '23 at 04:18
7

After a lunch break, I launched android studio and then my Directions classes are generated. I don't know why I couldn't use them earlier.

Skunka
  • 525
  • 2
  • 6
  • 22
  • 4
    It is because you need to build Application – Machhindra Neupane Jan 07 '20 at 08:18
  • 1
    Actually, I remember well building the application several times, that's why I asked help here. I'm pretty sur there was a cache conflict, I should have unvalidate it but it's too late now ^^ – Skunka Mar 10 '22 at 13:43
6

From: https://developer.android.com/guide/navigation/navigation-getting-started

The recommended way to navigate between destinations is to use the Safe Args Gradle plugin. This plugin generates simple object and builder classes that enable type-safe navigation and argument passing between destinations.

To add Safe Args to your project, include the following classpath in your top level build.gradle file:

buildscript {
repositories {
    google()
}
dependencies {
    def nav_version = "2.3.5"
    classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
}

}

To generate Java language code suitable for Java or mixed Java and Kotlin modules, add this line to your app or module's build.gradle file:

apply plugin: "androidx.navigation.safeargs"

You must have android.useAndroidX=true in your gradle.properties file as per Migrating to AndroidX.

After you enable Safe Args, the plugin generates code that contains classes and methods for each action you've defined.

Babak Karchini
  • 155
  • 1
  • 8