Soucis fonctionnement avec ChipGroup et chip

CR16_Padawan Messages postés 61 Date d'inscription mercredi 7 juin 2023 Statut Membre Dernière intervention 22 septembre 2024 - 9 janv. 2024 à 19:50
BunoCS Messages postés 15495 Date d'inscription lundi 11 juillet 2005 Statut Modérateur Dernière intervention 23 octobre 2024 - 18 janv. 2024 à 17:11

Bonjour,

j'utilise un ChipGroup avec chip dynamiques mais ça ne fonctionne pas bien sur mon appli.

parfois je ne peux pas du tout sélectionner un bouton et parfois après 1 ou 2 sélections, crash de l'appli.

pourriez-vous me dire si mon code fonctionne chez vous ou si vous voyez le problème?

mon logcat m'indique ceci:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.CharSequence android.widget.TextView.getText()' on a null object reference

Code TestChip :

package fr.xx.xxx.tests;

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

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.google.android.material.chip.Chip;
import com.google.android.material.chip.ChipGroup;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import fr.xx.xxx.R;
import fr.xx.xxx.databinding.LayoutTestBinding;

public class TestLayout extends AppCompatActivity {

    private LayoutTestBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = LayoutTestBinding.inflate(getLayoutInflater());
        View view = binding.getRoot();
        setContentView(view);

        TextView textView = binding.textView;
        ChipGroup chipGroup = binding.chipGroup;

        ArrayList<String> arrayList = new ArrayList<>();

        arrayList.add("A");
        arrayList.add("B");

        arrayList.add("C");
        arrayList.add("D");

        arrayLis.add("E");
        arrayList.add("F");
        arrayList.add("G");
        arrayList.add("H");

        Random random = new Random();
        for (String s : arrayList) {
            Chip chip = (Chip) LayoutInflater.from(TestLayout.this).inflate(R.layout.chip_layout, null);
            chip.setText(s);
            chip.setId(random.nextInt());
            chipGroup.addView(chip);

        }

        chipGroup.setOnCheckedStateChangeListener(new ChipGroup.OnCheckedStateChangeListener() {

            @Override
            public void onCheckedChanged(@NonNull ChipGroup group, @NonNull List<Integer> checkedIds) {

                if (checkedIds.isEmpty()) {
                    textView.setText("Rien de sélectionné");
                }else{
                    StringBuilder stringBuilder = new StringBuilder();
                    for (int i: checkedIds) {
                        Chip chip = findViewById(i);
                        stringBuilder.append(", ").append(chip.getText());
                    }
                    textView.setText("choisi quelquechose: " + stringBuilder.toString().replaceFirst(",",""));
                }
            }
        });
    }
 }

layout_test.xml :

<?xml version="1.0" encoding="utf-8"?>
< RelativeLayout

    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center_horizontal" >

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Select"

            android:layout_alignBottom="@+id/flPar"
            android:layout_marginEnd="@dimen/_10dp"

            android:layout_marginBottom="10dp"
            android:layout_toEndOf="@+id/flPar" />

        <com.google.android.material.chip.ChipGroup

            android:id="@+id/chipGroup"

            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"

            android:layout_below="@+id/flCom">

        </com.google.android.material.chip.ChipGroup>

    </RelativeLayout>



</LinearLayout>

Merci par avance pour vos solutions.


A voir également:

6 réponses

BunoCS Messages postés 15495 Date d'inscription lundi 11 juillet 2005 Statut Modérateur Dernière intervention 23 octobre 2024 3 911
10 janv. 2024 à 09:56

Hello,

J'ai fait quelques modifs dans ton code.

J'ai d'abord nettoyé ton Layout, pour supprimer des contraintes qui n'existent pas (mais j'imagine que c'est parce que tu as clean ton code avant de poster)

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

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="10dp"
        android:layout_marginBottom="10dp"
        />

    <com.google.android.material.chip.ChipGroup
        android:id="@+id/chipGroup"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp">

    </com.google.android.material.chip.ChipGroup>

</RelativeLayout>

Ensuite, dans le code, je crée les Chips comme ceci, avec le layout de base:

Random random = new Random();
for (String s : arrayList) {
  Chip chip = new Chip(getContext());
  chip.setText(s);
  chip.setId(random.nextInt());
  chip.setCheckable(true);  // important si tu veux utiliser la callback setOnCheckedStateChangeListener
  binding.chipGroup.addView(chip);
}

J'ai ajouté l'attribut checkable pour pouvoir utiliser la callback OnCheckedStateChangeListener. Et avec ceci, je vois bien les items que j'ai sélectionnés.


0
CR16_Padawan Messages postés 61 Date d'inscription mercredi 7 juin 2023 Statut Membre Dernière intervention 22 septembre 2024 1
12 janv. 2024 à 15:38

Bonjour Bruno,

j'ai testé tes modifs mais le problème est identique. je ne comprends pas pourquoi?

Je me demande pourquoi mon Logcat me dit que mon textview est null ?

widget.TextView.getText()' on a null object reference

 merci


0
BunoCS Messages postés 15495 Date d'inscription lundi 11 juillet 2005 Statut Modérateur Dernière intervention 23 octobre 2024 3 911
12 janv. 2024 à 16:55

C'est quoi ton widget ? Tu es sûr d'avoir une TextView dedans ?

Comment construis-tu tes chips ?

0
CR16_Padawan Messages postés 61 Date d'inscription mercredi 7 juin 2023 Statut Membre Dernière intervention 22 septembre 2024 1
12 janv. 2024 à 17:37

j'ai un 

chip_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.chip.Chip

    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    style="@style/Widget.Material3.Chip.Filter.Elevated"
    android:id="@+id/chipGroup"
    >

</com.google.android.material.chip.Chip>

layout_test.xml

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

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="10dp"
        android:layout_marginBottom="10dp"
        />

    <com.google.android.material.chip.ChipGroup
        android:id="@+id/chipGroup"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp">

    </com.google.android.material.chip.ChipGroup>

</RelativeLayout>

TestLayout.java

package fr.xx.xxx.activities;

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

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.google.android.material.chip.Chip;
import com.google.android.material.chip.ChipGroup;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import fr.xx.xxx.R;
import fr.xx.xxx.databinding.LayoutTestBinding;

public class TestLayout extends AppCompatActivity {

    private LayoutTestBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = LayoutTestBinding.inflate(getLayoutInflater());
        View view = binding.getRoot();
        setContentView(view);

        TextView textView = binding.textView;
        ChipGroup chipGroup = binding.chipGroup;

        ArrayList<String> arrayList = new ArrayList<>();

        arrayList .add("A");
        arrayList .add("B");

        arrayList .add("C");
        arrayList .add("D");

        arrayList .add("E");
        arrayList .add("F");
        arrayList .add("G");
        arrayList .add("H");

        Random random = new Random();
        for (String s : arrayList ) {
            Chip chip = (Chip) LayoutInflater.from(TestLayout.this).inflate(R.layout.chip_layout, null);
            chip.setText(s);
            chip.setId(random.nextInt());
            chip.setCheckable(true);  // important si tu veux utiliser la callback setOnCheckedStateChangeListener
            binding.chipGroup.addView(chip);
        }

        chipGroup.setOnCheckedStateChangeListener(new ChipGroup.OnCheckedStateChangeListener() {

            @Override
            public void onCheckedChanged(@NonNull ChipGroup group, @NonNull List<Integer> checkedIds) {

                if (checkedIds.isEmpty()) {
                    textView.setText("Rien de sélectionné");
                }else{
                    StringBuilder stringBuilder = new StringBuilder();
                    for (int i: checkedIds) {
                        Chip chip = findViewById(i);
                        stringBuilder.append(",").append(chip.getText());
                    }
                    textView.setText("choisi quelquechose: " + stringBuilder.toString().replaceFirst(",",""));
                }
            }
        });
    }
 }

Merci d'être passé.


0
BunoCS Messages postés 15495 Date d'inscription lundi 11 juillet 2005 Statut Modérateur Dernière intervention 23 octobre 2024 3 911
12 janv. 2024 à 18:38

D'une, je ne vois pas de notion de "widget" dans le code que tu postes. Or, le code posté fonctionne, testé et approuvé. Donc l'erreur est ailleurs.

De deux, pour récupérer les chips sélectionnées, je fais plutôt ceci:

for (int i: checkedIds) {
  Chip chip = binding.getRoot().findViewById(i);
  stringBuilder.append(", ").append(chip.getText());
}
0
CR16_Padawan Messages postés 61 Date d'inscription mercredi 7 juin 2023 Statut Membre Dernière intervention 22 septembre 2024 1
12 janv. 2024 à 19:53

merci pour ton retour.

Dans TestLayout.java j'importe

android.widget.TextView;

Je procède toujours de la même façon sur tout mon projet et je n'ai pas de soucis a l'affichage.

ce qui m'intrigue en fait c'est que parfois je peux sélectionner 2 données avant que ça ne bug et parfois rien du tout;

je te joins mon logcat pour voir si je n'est rien raté.

FATAL EXCEPTION: main
                                                                                                    Process: fr.xx.testapp, PID: 11167
                                                                                                    java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.CharSequence android.widget.TextView.getText()' on a null object reference
                                                                                                    	at fr.xx.testapp.activities.TestLayout$1.onCheckedChanged(TestLayout.java:69)
                                                                                                    	at com.google.android.material.chip.ChipGroup$1.onCheckedStateChanged(ChipGroup.java:166)
                                                                                                    	at com.google.android.material.internal.CheckableGroup.onCheckedStateChanged(CheckableGroup.java:184)
                                                                                                    	at com.google.android.material.internal.CheckableGroup.access$300(CheckableGroup.java:43)
                                                                                                    	at com.google.android.material.internal.CheckableGroup$1.onCheckedChanged(CheckableGroup.java:83)
                                                                                                    	at com.google.android.material.internal.CheckableGroup$1.onCheckedChanged(CheckableGroup.java:79)
                                                                                                    	at com.google.android.material.chip.Chip.lambda$new$0$com-google-android-material-chip-Chip(Chip.java:264)
                                                                                                    	at com.google.android.material.chip.Chip$$ExternalSyntheticLambda0.onCheckedChanged(D8$$SyntheticClass)
                                                                                                    	at android.widget.CompoundButton.setChecked(CompoundButton.java:156)
                                                                                                    	at com.google.android.material.chip.Chip.setChecked(Chip.java:727)
                                                                                                    	at android.widget.CompoundButton.toggle(CompoundButton.java:115)
                                                                                                    	at android.widget.CompoundButton.performClick(CompoundButton.java:120)
                                                                                                    	at android.view.View$PerformClick.run(View.java:22265)
                                                                                                    	at android.os.Handler.handleCallback(Handler.java:751)
                                                                                                    	at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                                    	at android.os.Looper.loop(Looper.java:154)
                                                                                                    	at android.app.ActivityThread.main(ActivityThread.java:6077)
                                                                                                    	at java.lang.reflect.Method.invoke(Native Method)
                                                                                                    	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
                                                                                                    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)

0
BunoCS Messages postés 15495 Date d'inscription lundi 11 juillet 2005 Statut Modérateur Dernière intervention 23 octobre 2024 3 911
12 janv. 2024 à 22:39

Essaies de lancer ton app en mettant un point d'arrêt dans la callback. C'est comme si tu n'arrivais pas à récupérer la textView. D'ailleurs, essaies plutôt d'utiliser le binding au lieu d'une variable locale pour tes composants. Ça vient peut être de là 

0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
CR16_Padawan Messages postés 61 Date d'inscription mercredi 7 juin 2023 Statut Membre Dernière intervention 22 septembre 2024 1
13 janv. 2024 à 10:51

Bonjour Bruno,

j'ai fais ce que tu m'as conseillé, utiliser binding plutôt qu'une variable et utiliser des points d'arrêts.

Après plusieurs tests il me semble constater que le problème vient lors du chargement de la variable "chip" (ligne 70)

Lig70   Chip chip = binding.getRoot().findViewById(i);

capture écran après 2 choix:

dans l'onglet "Problems" il y a également cette ligne 

Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)

0
BunoCS Messages postés 15495 Date d'inscription lundi 11 juillet 2005 Statut Modérateur Dernière intervention 23 octobre 2024 3 911
17 janv. 2024 à 10:06

Hum...

Essaie de faire le findView sur le group et non sur la root:

Chip chip = group.findViewById(i);

En passant, il est très rare, voire même déconseillé, de créer des ID à la volée comme ça. Généralement, pour retrouver des vues, on utilise plutôt l'attribut Tag

0
CR16_Padawan Messages postés 61 Date d'inscription mercredi 7 juin 2023 Statut Membre Dernière intervention 22 septembre 2024 1
18 janv. 2024 à 14:26

Bonjour Bruno,

merci pour cette réponse mais ça ne fonctionne toujours pas.

Comment puis-je procéder pour utiliser l'attribut Tag ?

As-tu quelque chose à me proposer (code, vidéo, tuto...?)

Merci d'avance.


0
BunoCS Messages postés 15495 Date d'inscription lundi 11 juillet 2005 Statut Modérateur Dernière intervention 23 octobre 2024 3 911
18 janv. 2024 à 17:11

C'est comme l'attribut ID: setTag(), getTag(), findViewWithTag()

https://developer.android.com/reference/android/view/View#findViewWithTag(java.lang.Object)

0