Dialog verschwindet

  • Antworten:9
Robbiani Renato
  • Forum-Beiträge: 602

30.05.2020, 15:57:19 via Website

Hallo zusammen

Am Ende der App wird mit einem Dialog gefragt, ob die App beendet werden soll oder nicht.

package ch.robbisoft.quadrate

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import java.util.*
import android.os.Handler
import android.widget.*
import androidx.appcompat.app.AlertDialog
import kotlin.random.Random

class MainActivity : AppCompatActivity() {

// Initialisierungen
val farbeArray = intArrayOf(
    R.drawable.rot,
    R.drawable.gelb,
    R.drawable.gruen,
    R.drawable.blau,
    R.drawable.cyan,
    R.drawable.ocker,
    R.drawable.magenta,
    R.drawable.schwarz,
    R.drawable.weiss)

var flBreite : Int = 0
var flHoehe : Int = 0
var punkte = 0
var meldung : AlertDialog.Builder? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    flBreite = resources.displayMetrics.widthPixels
    flHoehe = resources.displayMetrics.heightPixels

    meldung = AlertDialog.Builder(this)

    start()

        meldung!!.setTitle("Weiter machen")
        meldung!!.setMessage("Nochmals Spielen?")
        meldung!!.setPositiveButton("Ja") {_, _ ->
            start()
        }
        meldung!!.setNegativeButton("Nein") {_, _ ->
            finish()
        }
}

private fun start(){
    punkte = 0
    //Zufällige Farbe beim Start
    var farbeZiel = farbeArray[Random.nextInt(farbeArray.size)]
    var ziel = ivZiel
    ziel.setImageResource(farbeZiel)
    val zeitStart = Calendar.getInstance().time.time
    var spielAktiv = true

    //Neues Quadrat erzeugen
    val neuHandler = Handler()
    val neuObjekt = object : Runnable {
        override fun run() {
            val ivNeu = ImageView(this@MainActivity)
            val farbe = farbeArray[Random.nextInt(farbeArray.size)]
            ivNeu.tag = farbe
            ivNeu.setImageResource(farbe)

            val lp = FrameLayout.LayoutParams(
                LinearLayout.LayoutParams.WRAP_CONTENT,
                LinearLayout.LayoutParams.WRAP_CONTENT
            )
            lp.leftMargin = (Random.nextDouble(0.05, 0.8) * flBreite).toInt()
            lp.topMargin = (Random.nextDouble(0.05, 0.8) * flHoehe).toInt()
            ivNeu.layoutParams = lp
            flGesamt.addView(ivNeu)

            ivNeu.setOnClickListener {
                flGesamt.removeView(ivNeu)
                if (spielAktiv) {
                    punkte += if (ivNeu.tag == farbeZiel) 1 else -1
                    tvPunkte.text = "Punkte: %d".format(punkte)
                }
            }

            val loeschHandler = Handler()
            val loeschObjekt = object : Runnable {
                override fun run() {
                    flGesamt.removeView(ivNeu)
                }
            }
            loeschHandler.postDelayed(loeschObjekt, 5000L)
            neuHandler.postDelayed(this, 500L)
        }
    }
    neuHandler.postDelayed(neuObjekt, 500L)

    //Zielfarbe ändern
    val zielHandler = Handler()
    val zielObjekt = object : Runnable {
        override fun run() {
            val farbeZielAlt = farbeZiel
            while (farbeZielAlt == farbeZiel)
                farbeZiel = farbeArray[Random.nextInt(farbeArray.size)]
            flGesamt.removeView(ziel)
            ziel = ImageView(this@MainActivity)
            ziel.setImageResource(farbeZiel)
            val lp = FrameLayout.LayoutParams(
                LinearLayout.LayoutParams.WRAP_CONTENT,
                LinearLayout.LayoutParams.WRAP_CONTENT
            )
            ziel.layoutParams = lp
            flGesamt.addView(ziel)
            zielHandler.postDelayed(this, 5000L)
        }

    }
    zielHandler.postDelayed(zielObjekt, 5000L)

    //Zeitanzeige
    val zeitHandler = Handler()
    val zeitObjekt = object : Runnable {
        override fun run() {
            val zeitAktuell = Calendar.getInstance().time.time
            val zeitDifferenz = zeitAktuell - zeitStart
            val zeitAusgabe = 60 - zeitDifferenz / 1000
            brZeit.progress = (180 / 60 * zeitAusgabe).toInt()
            if (zeitDifferenz > 60000L) {
                spielAktiv = false
                neuHandler.removeCallbacks(neuObjekt)
                zielHandler.removeCallbacks(zielObjekt)
                meldung!!.show()
            } else {
                zeitHandler.postDelayed(this, 1000L)
            }
        }
    }
    zeitHandler.postDelayed(zeitObjekt, 1000L)
}

}

Wenn der Dialog angezeigt wird, kann ich irgend wo auf den Bildschirm tippen und der Dialog verschwindet und die App bleibt stehen. Was kann ich machen, dass nur Klicks vom Dialog akzeptiert werden?

Gruss Renato

Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

30.05.2020, 17:34:13 via Website

Das sollte ich auch auf Kotlin übertragen lassen:
https://stackoverflow.com/a/42254622/4975457

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.527

31.05.2020, 11:55:47 via Website

Hallo
In der oCreate startest du ja deine Methode start bevor du dein Dialog inizalirst. In der Methode start rufst du in einem runnable die Show Methode des Dialogs auf und zeigst somit den Dialog an.

Erste Frage wieso rufst du das Start und somit das anzeigen Dialogs auf obwohl du noch gar nicht deine Button gesetzt hast.

Zweitens wieso rufst du beim positiv Button wider deine start
Methode (oder Funktion wir haben ja Kotlin) auf ? Somit startest du alles wider neu.

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

31.05.2020, 18:15:34 via Website

Ciao Jokel

Ich weiss nicht ob es die beste Lösung ist. Aber so funktioniert es. Meine App ist ein Spiel. Nach einer Spielrunde möchte ich entscheiden können, ob ich nochmals eine Runde spielen oder die App beenden möchte.

Ich habe das Problem mit dem Klicken so gelöst, in dem ich auf der Aktivity ein Klicklisener setzte und wenn dieser ausgelöst wird, wird das Spiel neu gestartet.

Gruss Renato

Hilfreich?
Kommentieren
Ludy
  • Admin
  • Forum-Beiträge: 7.957

31.05.2020, 19:01:21 via Website

Hallo zusammen,

ich denke das sollte funktionieren!

package ch.robbisoft.quadrate

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import java.util.*
import android.os.Handler
import android.widget.*
import androidx.appcompat.app.AlertDialog
import kotlin.random.Random

class MainActivity : AppCompatActivity() {

    // Initialisierungen
    val farbeArray = intArrayOf(
        R.drawable.rot,
        R.drawable.gelb,
        R.drawable.gruen,
        R.drawable.blau,
        R.drawable.cyan,
        R.drawable.ocker,
        R.drawable.magenta,
        R.drawable.schwarz,
        R.drawable.weiss)

    var flBreite : Int = 0
    var flHoehe : Int = 0
    var punkte = 0
    private lateinit var meldung: AlertDialog.Builder

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        flBreite = resources.displayMetrics.widthPixels
        flHoehe = resources.displayMetrics.heightPixels

        meldung = AlertDialog.Builder(this).apply {
            setTitle("Weiter machen")
            setMessage("Nochmals Spielen?")
            setPositiveButton("Ja") { _, _ ->
                start()
            }
            setNegativeButton("Nein") { _, _ ->
                finish()
            }
            setCancelable(false) // Verhindert das abbrechen des Dialogs
        }
        start()
    }

    private fun start(){
        punkte = 0
        //Zufällige Farbe beim Start
        var farbeZiel = farbeArray[Random.nextInt(farbeArray.size)]
        var ziel = ivZiel
        ziel.setImageResource(farbeZiel)
        val zeitStart = Calendar.getInstance().time.time
        var spielAktiv = true

        //Neues Quadrat erzeugen
        val neuHandler = Handler()
        val neuObjekt = object : Runnable {
            override fun run() {
                val ivNeu = ImageView(this@MainActivity)
                val farbe = farbeArray[Random.nextInt(farbeArray.size)]
                ivNeu.tag = farbe
                ivNeu.setImageResource(farbe)

                val lp = FrameLayout.LayoutParams(
                    LinearLayout.LayoutParams.WRAP_CONTENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT
                )
                lp.leftMargin = (Random.nextDouble(0.05, 0.8) * flBreite).toInt()
                lp.topMargin = (Random.nextDouble(0.05, 0.8) * flHoehe).toInt()
                ivNeu.layoutParams = lp
                flGesamt.addView(ivNeu)

                ivNeu.setOnClickListener {
                    flGesamt.removeView(ivNeu)
                    if (spielAktiv) {
                        punkte += if (ivNeu.tag == farbeZiel) 1 else -1
                        tvPunkte.text = "Punkte: %d".format(punkte)
                    }
                }

                val loeschHandler = Handler()
                val loeschObjekt = object : Runnable {
                    override fun run() {
                        flGesamt.removeView(ivNeu)
                    }
                }
                loeschHandler.postDelayed(loeschObjekt, 5000L)
                neuHandler.postDelayed(this, 500L)
            }
        }
        neuHandler.postDelayed(neuObjekt, 500L)

        //Zielfarbe ändern
        val zielHandler = Handler()
        val zielObjekt = object : Runnable {
            override fun run() {
                val farbeZielAlt = farbeZiel
                while (farbeZielAlt == farbeZiel)
                    farbeZiel = farbeArray[Random.nextInt(farbeArray.size)]
                flGesamt.removeView(ziel)
                ziel = ImageView(this@MainActivity)
                ziel.setImageResource(farbeZiel)
                val lp = FrameLayout.LayoutParams(
                    LinearLayout.LayoutParams.WRAP_CONTENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT
                )
                ziel.layoutParams = lp
                flGesamt.addView(ziel)
                zielHandler.postDelayed(this, 5000L)
            }

        }
        zielHandler.postDelayed(zielObjekt, 5000L)

        //Zeitanzeige
        val zeitHandler = Handler()
        val zeitObjekt = object : Runnable {
            override fun run() {
                val zeitAktuell = Calendar.getInstance().time.time
                val zeitDifferenz = zeitAktuell - zeitStart
                val zeitAusgabe = 60 - zeitDifferenz / 1000
                brZeit.progress = (180 / 60 * zeitAusgabe).toInt()
                if (zeitDifferenz > 60000L) {
                    spielAktiv = false
                    neuHandler.removeCallbacks(neuObjekt)
                    zielHandler.removeCallbacks(zielObjekt)
                    meldung.show()
                } else {
                    zeitHandler.postDelayed(this, 1000L)
                }
            }
        }
        zeitHandler.postDelayed(zeitObjekt, 1000L)
    }
}

Gruß Ludy (App Entwickler)

Mein Beitrag hat dir geholfen? Lass doch ein "Danke" da.☺

☕ Buy Me A Coffee ☕

Lebensmittelwarnung-App

✨Meine Wunschliste✨

📲Telegram NextPit News📲

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.527

31.05.2020, 19:14:13 via Website

Ludy ist eigentlich genau das was ich gesagt habe bevor er die listner gesetz hat hatte er das show gemacht.
Nun machst du das auch richtiger weiße nach dem setzen der listner.
Also der Aufruf der Methode start.

Das hätte und sollte er eigentlich selber finden.

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.527

31.05.2020, 22:32:18 via Website

Es macht für mich nicht viel Sinn das show auszuführen. Also den Dialog anzuzeigen aber die button noch nicht definiert zu habe. Also ob es nur ein ok, oder positiv und negativ, oder alle drei positiv negativ und neutral Button werden sollen. Also auch die entstehenden Listner gesetzt sind.
setCancelable heißt das es ein Dialog mit positiv und negativ button ist.

Unsinnig ist drotzden ein show zu machen ohne die Parameter für den Dialog fest zu legen.

— geändert am 31.05.2020, 22:39:33

Hilfreich?
Kommentieren
Ludy
  • Admin
  • Forum-Beiträge: 7.957

31.05.2020, 22:43:33 via App

Okay, du hast Recht, das macht natürlich keinen Sinn start() vorher aufzurufen.

Aber: setCancelable = false verhindert das du beim Drücken außerhalb des Dialogs diesen abbrechen kannst, auch ohne Button.

Gruß Ludy (App Entwickler)

Mein Beitrag hat dir geholfen? Lass doch ein "Danke" da.☺

☕ Buy Me A Coffee ☕

Lebensmittelwarnung-App

✨Meine Wunschliste✨

📲Telegram NextPit News📲

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

01.06.2020, 11:13:22 via Website

Danke für eure Antworten.

Genau so wie es gesagt wurde. Wenn ich alle Tipps umsetzen und die Zeile

meldung!!.setCancelable(false)

einfüge, funktioniert es.

Gruss Renato

Hilfreich?
Kommentieren