0
votes

Android Kotlin: vue personnalisée provoquant un crash lors de la modification des fragments

Dans mon projet, j'ai trois fragments attachés à une activité, et l'un de ces fragments, encore une fois, des fragments qui affichent des textes à l'aide de vues personnalisées. Ce sont donc essentiellement des fragments dans un fragment.

Dans le fragment principal, j'ai mis ces codes pour basculer entre les fragments d'affichage de texte. Il est déclenché sur les codes passés par ses fragments enfants.

class TypeWriterView: AppCompatTextView {
  constructor(context: Context) : super(context)
  constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

  suspend fun commence(txt: CharSequence?, delay: Long, animOnOff: Boolean) {
    if (txt != null) {
        if(animOnOff) {
            var index = 0
            while (index < txt.length) {
                text = txt.subSequence(0, ++index)
                delay(delay)
            }
        } else {text = txt}
    } else return
  }
  fun commenceOnLifecycle(owner: LifecycleOwner, txt: CharSequence?, delay: Long, animOnOff: Boolean): Job =
    owner.lifecycleScope.launch { commence(txt, delay, animOnOff) }
}

Et les fragments d'affichage de texte ont des vues personnalisées - AppCompatTextView - qui affiche des textes.

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

<com.example.textia1.TypeWriterView
    android:id="@+id/x2Twv01"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textColor="@color/colorAccent" />

<TextView
    android:id="@+id/x2Choice01"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/X2toX1" />

<TextView
    android:id="@+id/x2Choice02"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/X2toX3" />

</LinearLayout>

J'ai trois fragments d'affichage de texte identiques pour l'instant et le premier fragment d'affichage de texte apparaît bien. Mais lorsque j'essaie de transmettre la valeur au fragment principal et de déclencher diagCommence (), l'application se bloque. Ce qui était étrange, c'est que lorsque j'essaie d'accéder au deuxième fragment d'affichage de texte, cela me donne une exception de pointeur nul.

Selon le journal, l'erreur a été invoquée dans la méthode commenceOnLifecycle (), qui appelle le AppCompatTextView que j'ai créé. Le déplacer vers différents cycles de vie tels que onCreate (), onViewCreated () ne semble pas résoudre ce problème. Je me demande ce que je manque?

Edit: Le XML de mise en page de SceneX2, qui est un fragment d'affichage de texte:

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    return inflater.inflate(R.layout.layoutx2, container, false)
}
override fun onStart() {
    super.onStart()
    val scene = getString(R.string.sceneX2)
    tv01.commenceOnLifecycle(SceneX2(), scene, textanimspeed.toLong(), textanim) // the custom view that displays texts, triggers NPE
}

et le TextView personnalisé qui affiche le texte avec une animation de frappe:

private fun diagCommence(target: Fragment) {
    val transaction = activity?.supportFragmentManager?.beginTransaction()
    if (transaction != null) {
        transaction.replace(R.id.ig1_Diag_Layout, target)
        transaction.disallowAddToBackStack()
        transaction.commit()
    }
}


0 commentaires

3 Réponses :


0
votes

Si vous êtes en activité, vous devez utiliser fragmentManager. veuillez changer cette ligne

    val nextScene = fragmentManager?.beginTransaction()

à

    val nextScene = activity?.supportFragmentManager?.beginTransaction()


0 commentaires

1
votes

Essayez de remplacer votre code de fonction diagCommence par

class TypeWriterView(
    context: Context,
    attrs: AttributeSet
) : AppCompatTextView(context, attrs) {

Vous devez également initialiser votre vue onCreateView dans onCreateView . Tout d'abord, déclarez une variable globale

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val view = inflater.inflate(R.layout.layoutx2, container, false)
    
    tv01 = view.findViewById(R.id.x2Twv01)

    val scene = requireActivity().getString(R.string.sceneX2)
    tv01?.commenceOnLifecycle(SceneX2(), scene, textanimspeed.toLong(), textanim) // the custom view that displays texts
    
    return view
}

et éditez votre méthode onCreateView

private var tv01: TypeWriterView? = null

ÉDITER

Modifiez votre déclaration TypeWriterView comme

activity?.supportFragmentManager?.beginTransaction()
        ?.replace(R.id.ig1_Diag_Layout, target)
        ?.addToBackStack(null)
        ?.commit()


5 commentaires

Merci pour votre aimable aide. J'ai utilisé le deuxième code comme: private var tv01: AppCompatTextView? = null ai-je bien fait? Le suivant est également devenu comme ceci: tv01 = view?.findViewById(R.id.Sc_X2_tv01) Il y avait une erreur sans appel sécurisé. J'ai remplacé diagCommence et déplacé les codes dans onStart vers onCreate comme vous l'avez dit, mais cela ne fonctionne toujours pas et me donne NPE.


Essayez de déplacer le code dans onCreateView comme dans la réponse modifiée, notez également que j'appelle requireActivity() pour obtenir la chaîne à partir des ressources. Les variables globales textanimspeed et textanim sont- textanimspeed dans votre fragment?


Oui, ils le sont, et j'ai modifié le code, mais mettre AppCompatTextView dans <> AppCompatTextView erreur "Propriété getter ou setter attendue" et "Pas assez d'informations pour déduire la variable de type T" sur findViewById . Et aussi tv01?.commenceOnLifecycle() fait une erreur de "Référence non tv01?.commenceOnLifecycle() ", donc j'ai dû le laisser être ( Tv01.commenceOnLifecycle mais Tv01 est l'ID de mise en page). L'application lance toujours NPE lors de l'appel de commenceOnLifecycle() .


J'ai oublié de supprimer le <> wrapping AppCompatTextView . Pouvez-vous publier votre XML layoutx2?


D'accord, je l'ai posté ainsi que la vue de texte appcompat, juste au cas où.



0
votes

Assurez-vous d'utiliser childFragmentManager car childFragmentManager est associé à des fragments tels que supportFragmentManager est associé à une activity

private fun diagCommence(target: Fragment) {
    val transaction = childFragmentManager.beginTransaction()
    if (transaction != null) {
        transaction.replace(R.id.ig1_Diag_Layout, target)
        transaction.disallowAddToBackStack()
        transaction.commit()
    }
}


1 commentaires

Désolé mais il a tout fait, y compris pour afficher le prochain fragment, tout simplement pas fonctionner sur clic.