135 votes

ViewBinding - comment obtenir une liaison pour les mises en page incluses ?

En travaillant avec ViewBinding, j'ai rencontré quelques cas non documentés.

Premièrement : Comment obtenir une liaison pour les parties de la vue générique incluses, la liaison principale ne voit que les éléments de la vue principale ?

Deuxièmement : Comment obtenir une liaison pour les parties de la mise en page de type fusion incluses, alors que la liaison principale ne voit que les éléments de la mise en page principale ?

0 votes

L'autre moyen simple serait d'utiliser la bibliothèque de liaison de données. Enveloppez ensuite votre mise en page XML avec la balise <layout> pour que, si vous utilisez la bibliothèque, celle-ci génère automatiquement les classes nécessaires pour lier les vues de la mise en page avec vos objets de données. Honnêtement, je pense que c'est la voie à suivre. Suivez le guide aquí

1 votes

Bonjour, j'ai écrit un article de blog expliquant complètement la liaison de vue et la manipulation de la balise incluse avec la vérification des mises en page de fusion et d'inclusion. Androidbites|ViewBinding

0 votes

Je suis un peu coincé ici : stackoverflow.com/questions/67808297/

198voto

Artur Kasprzak Points 2999

En cas de :

  1. Inclure avec une mise en page générique (pas de nœud de fusion), nous devons attribuer un ID à la partie incluse, de cette façon, dans la liaison, nous aurons accès à la sous-partie incluse.

    <include android:id="@+id/your_id" layout="@layout/some_layout" />

De cette façon, dans votre code d'activité :

private lateinit var exampleBinding: ActivityExampleBinding  //activity_example.xml layout

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    exampleBinding = ActivityExampleBinding.inflate(layoutInflater)
    setContentView(exampleBinding.root)
    //we will be able to access included layouts view like this
    val includedView: View = exampleBinding.yourId.idOfIncludedView
//[...]
}
  1. Inclure avec le bloc de fusion dans la mise en page externe. Nous ne pouvons pas y ajouter d'ID car le bloc de fusion n'est pas une vue. Supposons que nous ayons un tel layout de fusion éternelle (merge_layout.xm) :

    <?xml version="1.0" encoding="utf-8"?> <merge 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" tools:showIn="@layout/activity_example">

    <TextView
        android:id="@+id/some_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World" />

    </merge>

Pour lier correctement une telle mise en page de fusion, nous devons :

Dans votre code d'activité :

private lateinit var exampleBinding: ActivityExampleBinding  //activity_example.xml layout
private lateinit var mergeBinding: MergeLayoutBinding  //merge_layout.xml layout

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    exampleBinding = ActivityExampleBinding.inflate(layoutInflater)
    //we need to bind the root layout with our binder for external layout
    mergeBinding = MergeLayoutBinding.bind(exampleBinding.root)
    setContentView(exampleBinding.root)
    //we will be able to access included in merge layout views like this
    val mergedView: View = mergeBinding.someView
//[...]
}

25voto

Emi Raz Points 1059

Votre première question, qui est de travailler avec une mise en page incluse en utilisant ViewBinding, peut être résolue très facilement.

En voici un exemple fragment principal.xml archivo

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view_main"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <include
        android:id="@+id/toolbar"
        layout="@layout/toolbar" />

</LinearLayout>

Et MainFragment.java peut être comme ceci

public class MeaningFragment extends Fragment {

    private MainFragmentBinding binding;
    private ToolbarBinding toolbarBinding;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

        binding = MainFragmentBinding.inflate(inflater, container, false);
        toolbarBinding = binding.toolbar;

        return binding.getRoot();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        toolbarBinding = null;
        binding = null;
    }
}

Maintenant, vous avez deux liaisons. L'une d'entre elles est la liaison par défaut et la suivante provient de la disposition incluse.

2 votes

La réponse est très simple et utilise la nouvelle syntaxe - tout fonctionne pour moi dans une activité non fragmentée avec une syntaxe similaire en onCreate() . Merci. (J'ai juste un peu de mal à utiliser pour une DrawerLayout )

1 votes

Je reçois un NPE d'exécution qui dit qu'il manque une vue requise avec l'ID blah.

1 votes

@Asim Peut-être que si vous changez votre disposition incluse de fusion à un certain viewGroup

6voto

Manav Adhyaru Points 41

Si vous voulez lier la mise en page incluse alors,

Pour l'activité

YourMainLayoutBinding mainLayoutBinding = MainLayoutBinding.inflate(getLayoutInflater);

View view = mainLayoutBinding.getRoot();

YourIncludedLayoutBinding includedLayoutBinding = YourIncludedLayoutBinding.bind(View);

Pour le fragment

YourMainLayoutBinding mainLayoutBinding = MainLayoutBinding.inflate(inflater,container,false);

View view = mainLayoutBinding.getRoot();

YourIncludedLayoutBinding includedLayoutBinding = YourIncludedLayoutBinding.bind(View);

Assurez-vous que la racine parentale de votre mise en page principale est LinearLayout, la disposition parent includedLayoutBinding est également une disposition linéaire.

2 votes

Il n'est pas nécessaire de lier explicitement la mise en page incluse, cela est fait automatiquement si vous spécifiez un id pour elle : <include android:id="@+id/myToolbar" layout="@layout/toolbar" /> . Après cela, le champ mainLayoutBinding.myToolbar contiendra une liaison imbriquée.

1voto

ss_ts Points 31

Supposons que j'inclue une mise en page dans mon activity_main.xml comme suit :

<include
    android:id="@+id/ll_layout1"
    layout="@layout/layout1"
    android:visibility="gone" />

Et supposons que je veuille changer sa visibilité. Je peux le faire comme suit :

activityMainBinding.llLayout1.root.visibility = View.VISIBLE

0voto

David Arribas Points 77

Dans le layout include, vous devez créer un layout Container et mettre ici l'id.

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/example"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent">
    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X