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

11

En travaillant avec ViewBinding, je rencontre peu de cas non documentés.

Premièrement: comment obtenir la liaison pour les pièces de disposition de vue générique incluses, la liaison principale ne voit que les éléments de la disposition principale?

Deuxièmement: comment obtenir la liaison pour les parties de disposition de type de fusion incluses, encore une fois la liaison principale ne voit que les éléments de la disposition principale?

Artur Kasprzak
la source

Réponses:

15

En cas de:

  1. Inclure avec la disposition générique (pas fusionner le noeud), 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. Disons que nous avons une telle disposition 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 disposition 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
//[...]
}
Artur Kasprzak
la source
1
Cela semble être un bug. Ça devrait juste marcher .
miguel
7

Votre première question, qui fonctionne avec une mise en page incluse à l'aide de ViewBinding, peut être résolue si facilement.

Voici un exemple de fichier main_fragment.xml

<?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 ça

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'un d'eux est celui par défaut et le suivant provient de la disposition incluse.

Emi Raz
la source
1
Réponse très simple et utilise la nouvelle syntaxe - tout cela fonctionne pour moi dans une activité non fragmentaire avec une syntaxe similaire dans onCreate(). Merci. (Juste avoir un peu de mal à utiliser pour un DrawerLayout)
Fat Monk
0

L'autre moyen simple serait d'utiliser la bibliothèque de liaison de données. Enveloppez ensuite votre disposition XML avec une balise afin que si vous utilisez la bibliothèque, elle génère automatiquement les classes requises pour lier les vues de la disposition à vos objets de données. Honnêtement, je pense que c'est la voie à suivre. Suivez le guide ici

Arun Gurung
la source