DialogFragment aus einem Adapter aufrufen

  • Antworten:8
  • Bentwortet
Robbiani Renato
  • Forum-Beiträge: 602

22.11.2021, 20:48:32 via Website

Hallo zusammen

Um den Inhalt meiner App zu erstellen verwende ich Fragmente. In den Fragmenten baue ich den Inhalt über Adapter auf. Nun möchte ich aus meinem Adapter heraus ein Dialogfragment aufrufen. Für den Aufruf benötige ich ein Fragmentmanager. Den erhalte ich über Umwegen von der Mainactivity

class TelAdapter(var context: Context) : BaseAdapter(), DialogInterface.OnClickListener{
und
private val ctx = context as AppCompatActivity

Somit kann ich den Dialog mit dem Fragmentmanager aufrufen

dialog.show(ctx.supportFragmentManager, DialogFrag.TAG)

Wenn ich den Dialog verlassen möchte, dann Zeigt mein "horcher" auf die MainActivity auf welcher es kein Dialoginterface hat. Das ganze läuft ins leere. Wenn ich den Context des Adappter verwende habe ich kein Fragmentmanager.

Irgend wie drehe ich mich im Kreis. Oder mache ich da einen falschen Ansatz.

Adapptr:

package ch.robbisoft.klassennotfall

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView
import android.widget.Toast
import android.content.DialogInterface
import androidx.appcompat.app.AppCompatActivity

class TelAdapter(var context: Context) : BaseAdapter(), DialogInterface.OnClickListener{

private val inflater = LayoutInflater.from(context)
private val ctx = context as AppCompatActivity
public var counter : Int = 0
public var nliste = arrayListOf<Person>()
private lateinit var dialog: DialogFrag

override fun getCount(): Int {
    return counter
}

override fun getItem(position: Int): Any {
    return nliste[position]
}

override fun getItemId(position: Int): Long {
    return position.toLong()
}

override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
    val view : View
    if (convertView != null) {
        view = convertView
    }else{
        view = inflater.inflate(R.layout.klass_list, parent, false)
    }

    val persdat = nliste[position]
    val obj_name = view.findViewById<TextView>(R.id.txt_klassname)
    val obj_mutter = view.findViewById<TextView>(R.id.txt_klassmutter)
    val obj_vater = view.findViewById<TextView>(R.id.txt_klassvater)
    val obj_allg = view.findViewById<TextView>(R.id.txt_klassallgemein)

    obj_name.text = persdat.pname
    obj_mutter.text = persdat.telmutter
    obj_vater.text = persdat.telvater
    obj_allg.text = persdat.telalg

    obj_name.setOnClickListener {
        Toast.makeText(ctx, "Das ist der Name " + persdat.pname, Toast.LENGTH_LONG).show()
    }
    obj_mutter.setOnClickListener {
        Toast.makeText(ctx, "Das ist die Mutter", Toast.LENGTH_LONG).show()
    }
    obj_vater.setOnClickListener {
        Toast.makeText(ctx, "Das ist der Vater", Toast.LENGTH_LONG).show()
    }
    obj_allg.setOnClickListener {
        Toast.makeText(ctx, "Das ist das Allgemeine", Toast.LENGTH_LONG).show()
    }

    obj_name.setOnLongClickListener {
        dialog = DialogFrag()
        dialog.persname = persdat.pname
        dialog.show(ctx.supportFragmentManager, DialogFrag.TAG)
        true
    }
    obj_mutter.setOnLongClickListener {
        Toast.makeText(ctx, "langer klick", Toast.LENGTH_LONG).show()
        true
    }
    obj_vater.setOnLongClickListener {
        Toast.makeText(ctx, "langer klick", Toast.LENGTH_LONG).show()
        true
    }
    obj_allg.setOnLongClickListener {
        Toast.makeText(ctx, "langer klick", Toast.LENGTH_LONG).show()
        true
    }

    return view
}

override fun onClick(dialog : DialogInterface?, was : Int) {
    var neu = 1
}

}

Dialogfragment:

package ch.robbisoft.klassennotfall

import android.app.AlertDialog
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import androidx.fragment.app.DialogFragment

class DialogFrag : DialogFragment() {

private lateinit var horcher :DialogInterface.OnClickListener
public var persname : String = ""

override fun onAttach(context: Context) {
    super.onAttach(context)
    if (context is DialogInterface.OnClickListener){
        horcher = context
    }
}

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    val dialog = AlertDialog.Builder(requireContext())
    dialog.setTitle(R.string.dia_titel)
    dialog.setMessage(getString(R.string.dia_meldung, persname))
    dialog.setCancelable(false)
    dialog.setPositiveButton(R.string.dia_ja, horcher)
    dialog.setNegativeButton(R.string.dai_nein, horcher)
    dialog.setNeutralButton(R.string.dia_neutral, horcher)
    return dialog.create()
}

companion object{
    val TAG = DialogFrag::class.simpleName
}

}

Gruss Renato

Kommentieren
Beste Antwort
Robbiani Renato
  • Forum-Beiträge: 602

04.12.2021, 21:14:37 via Website

Hallo zusammen

Nach 100000000000000000 von Versuchen habe ich es jetzt zum laufen gebracht.
Der Aufruf des Dialogs erfolgt wie folgt:

frage.show(childFragmentManager, DialogFrag.TAG)

und der Aufruf der Antwort mache ich wie folgt:

(parentFragment as? FragKlasseC)?.onItemClicked(1)

Es spielt nur zusammen wenn ich "childFragmentManager" zusammen mit "parntFragment" verwende.

Gruss Renato

Hilfreich?
Kommentieren
Rafael K.
  • Forum-Beiträge: 2.359

23.11.2021, 09:31:32 via Website

Puh...wo soll ich anfangen?
Ich hatte dir ja gestern den Tipp gegeben direkt die Activity in den Adapter rein zu reichen.
Ich verstehe nicht, warum Du stattdessen einen cast machst.

private val ctx = context as AppCompatActivity

Das zerstört die komplette Typsicherheit.

Zudem ist das Konstrukt mit dem Listener auf dem Dialog komplett falsch herum aufgezogen.
Du musst da nichts in onAttach machen. Zudem ist eine Activity NIE Instanz von DialogInterface.OnClickListener. Warum auch? Sie ist kein Dialog.

Alles was du tun musst ist:

.setNeutralButton("Text") { _, _ ->
    dismiss()
    doSomeOtherStuff()
}
Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 602

24.11.2021, 14:49:02 via Website

Ciao Rafael

Danke für deine Antwort.
Das komische Konstrukt mit dem Cast habe ich nur aus einem Grund gemacht.

cadapter = TelAdapter(requireContext())//requireContext()
    if (cadapter != null) {
        cadapter.counter = namenliste.count()
        cadapter.nliste = namenliste
        listec = view.findViewById<ListView>(R.id.list_namec)
        listec.adapter = cadapter
    }

Beim Initialisieren des Adapters

cadapter = TelAdapter(requireContext())

kriegte ich einfach den "requireContext()" nicht weg. Wenn ich dein Vorschlag einbaue, dann hat er ein Problem. Also machte ich ein Cast.

Bei dem zweiten Hinweis gebe ich dir Recht. So wie du das vorschlägst funktioniert es. Dies tut es bei mir auch. Ich möchte aber nach dem Schliessen des Dialogs wieder zu meinem Adapter zurückkehren. Denn dort habe ich meine Daten und weis was zumachen ist. Darum mache ich den Aufruf über einen Clicklistener.

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    val dialog = AlertDialog.Builder(requireContext())
    dialog.setTitle(R.string.dia_titel)
    dialog.setMessage(getString(R.string.dia_meldung, persname))
    dialog.setCancelable(false)
    dialog.setPositiveButton(R.string.dia_ja, horcher)
    dialog.setNegativeButton(R.string.dai_nein, horcher)
    dialog.setNeutralButton(R.string.dia_neutral, horcher)
    return dialog.create()
}

Abfangen des Klicks im Adapter:

override fun onClick(dialog : DialogInterface?, was : Int) {
var neu = 1
}

Den Listener muss ich in OnAttach initialisieren. Genau das funktioniert nicht, denn ich habe den Klicklistener im Adatper aber der Context zeigt auf meine MainActivity und dort habe ich kein listener. Darum greift meine "horcher" ins leere.

Ich muss hinkriegen, dass der Context auf den Adapter zeigt. Aber dies ist unmöglich, da ich dann kein Fragmentmanager mehr habe.

Gruss Renato

Hilfreich?
Kommentieren
Rafael K.
  • Forum-Beiträge: 2.359

24.11.2021, 15:53:33 via Website

Warum nutzt du nicht requireActivity() ?

Den Listener muss ich in OnAttach initialisieren.

NEIN ! This is not how this works.

Gib einfach deiner Activity eine Methode als Callback. z.B.

fun onItemClicked(index: Int)

Dann machst Du im DialogFragment

(activity as? NameDeinerActivity)?.onItemClicked(index)
Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 602

26.11.2021, 21:46:18 via Website

Ciao Rafael

Funktioniert leider nicht. Oder ich verstehe dich Falsch.

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    val dialog = AlertDialog.Builder(requireContext())
    dialog.setTitle(R.string.dia_titel)
    dialog.setMessage(getString(R.string.dia_meldung, persname))
    dialog.setCancelable(false)
    dialog.setPositiveButton(R.string.dia_ja){_, _ ->
        (activity as? TelAdapter)?.onItemClicked(1)
    }
    dialog.setNegativeButton(R.string.dai_nein){_, _ ->
        (activity as? TelAdapter)?.onItemClicked(2)
    }
    dialog.setNeutralButton(R.string.dia_neutral){_, _ ->
        (activity as? TelAdapter)?.onItemClicked(3)
    }
    return dialog.create()
}

Mit oben stehendem Code lässt sich das Projekt compilieren und ausführen aber er kommt bei der "onItemClicked" Methode nicht vorbei.

Ich habe noch folgendes versucht. Anstelle von

(activity as? TelAdapter)?.onItemClicked(3)

habe ich folgendes erstellt

val objekt = TelAdapter(requireContext())

objekt.onItemClicked(3)

Da kommt er bei der Methode vorbei hat aber eine neue Instanz des Adapters und durch das nicht mehr die benötigten Daten.

Ich denke, dass das einfach nicht geht wenn man aus einem Adapter ein Fragmentdialog aufruft und zurück.

Gruss Renato

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 602

28.11.2021, 18:00:27 via Website

Ciao Rafael

Danke für deine Hilfe und die Geduld.
Ich habe dein Tipp umgesetzt. Führt ebenfalls nicht zum Ziel. Ich habe die Methode angelegt. Aber das Programm läuft nicht durch. Das einzige was neu ist, die App stürzt nicht mehr ab.

Aber ich denke, dass das einfach so nicht geht. Ich werde den Dialog lokal erstellen. Vielleicht geht das. Mal schauen.

Gruss Renato

Hilfreich?
Kommentieren
Beste Antwort
Robbiani Renato
  • Forum-Beiträge: 602

04.12.2021, 21:14:37 via Website

Hallo zusammen

Nach 100000000000000000 von Versuchen habe ich es jetzt zum laufen gebracht.
Der Aufruf des Dialogs erfolgt wie folgt:

frage.show(childFragmentManager, DialogFrag.TAG)

und der Aufruf der Antwort mache ich wie folgt:

(parentFragment as? FragKlasseC)?.onItemClicked(1)

Es spielt nur zusammen wenn ich "childFragmentManager" zusammen mit "parntFragment" verwende.

Gruss Renato

Hilfreich?
Kommentieren