Запретить переход назад, пока пользователь не ответит AlertDialog - PullRequest
1 голос
/ 14 марта 2020

У меня есть приложение iOS, и теперь я портирую его на Android с Kotlin. Но я застрял в очень простом случае. Существует фрагмент EditText во фрагменте, и я хочу спросить пользователя, хочет ли он / она сохранить перед тем, как оставить фрагмент, если что-то было записано в EditText.

Я могу обработать кнопку возврата с помощью OnBackPressedCallback и handleOnBackPressed и показать пользователю AlertDialog, но фрагмент закрывается, не дожидаясь ответа пользователя. Но я не хочу этого, не возможно дождаться ответа пользователя, а затем всплыть на предыдущий фрагмент? Потому что я должен сохранить текст до закрытия фрагмента.

Вот мой код

package info.airportnotes.maxipower.ui.note

import android.content.DialogInterface
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.findNavController
import com.google.android.material.floatingactionbutton.FloatingActionButton
import es.dmoral.toasty.Toasty
import info.airportnotes.maxipower.MainActivity
import info.airportnotes.maxipower.R
import info.airportnotes.maxipower.model.Status
import info.airportnotes.maxipower.utils.AirportNotesApp
import info.airportnotes.maxipower.utils.AppPreferences
import info.airportnotes.maxipower.utils.isNetworkAvailable
import info.airportnotes.maxipower.viewmodel.NewNoteViewModel


class NewNoteFragment : Fragment() {
    private var airportID: Long? = null
    private lateinit var viewModel: NewNoteViewModel
    private lateinit var builder : AlertDialog.Builder
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val view= inflater.inflate(R.layout.fragment_new_note, container, false)
        (activity as MainActivity).supportActionBar?.title =  getString(R.string.new_note)
        viewModel =
            ViewModelProvider.NewInstanceFactory().create(NewNoteViewModel::class.java)
        airportID = arguments?.getLong("airportID") ?: 0
        viewModel.airportID = airportID
        viewModel.refresh()

        val fab: View = view.findViewById<FloatingActionButton>(R.id.sendNote)
        if (!AppPreferences.isUserLoggedIn) {
            fab.visibility = View.INVISIBLE
            val noLoginBuilder = AlertDialog.Builder(activity as MainActivity)
            noLoginBuilder?.setMessage(getString(R.string.you_should_login))
                ?.setNeutralButton(getString(R.string.ok_title)) { _, _ ->

                }
            noLoginBuilder?.create()?.show()
        }
        fab.setOnClickListener {
            val text = view.findViewById<EditText>(R.id.noteText)
            if(text.text.toString().isEmpty()) return@setOnClickListener
            if (AirportNotesApp.appContext.isNetworkAvailable()) {
                viewModel.addNote(
                    text.text.toString(),
                    airportID!!, viewModel.filteredLang.value?.Code!!, AppPreferences.userID,
                    onFinish = {
                        it?.let {
                            if (it.status == Status.Success) {
                                Toasty.success(
                                    AirportNotesApp.appContext,
                                    getString(R.string.your_note_added),
                                    Toast.LENGTH_LONG,
                                    true
                                ).show();

                                if (AppPreferences.preferredLanguage.isNullOrEmpty() ||
                                    (AppPreferences.preferredLanguage.isNullOrBlank() && !AppPreferences.preferredLanguage.contentEquals(
                                        viewModel.filteredLang.value?.Code.toString()
                                    ))
                                ) {
                                    val yesNoBuilder = AlertDialog.Builder(activity as MainActivity)
                                    val lang = viewModel.filteredLang.value?.Title
                                    yesNoBuilder?.setMessage(
                                            resources.getString(
                                                R.string.ask_for_preferred_lang,
                                                lang
                                            )
                                        )
                                        ?.setPositiveButton(
                                            getString(R.string.yes_please)
                                        ) { _, _ ->
                                            AppPreferences.preferredLanguage =
                                                viewModel.filteredLang.value?.Code.toString()
                                            view.findNavController().popBackStack()
                                        }?.setNegativeButton(
                                            getString(R.string.no_i_dont_want)
                                        ) { _, _ ->
                                            view.findNavController().popBackStack()
                                        }
                                    yesNoBuilder?.create()?.show()
                                }
                                else {
                                    view.findNavController().popBackStack()
                                }

                            } else {
                                Toasty.error(
                                    AirportNotesApp.appContext,
                                    it.message,
                                    Toast.LENGTH_LONG,
                                    true
                                ).show();
                                view.findNavController().popBackStack()
                            }
                        }
                    }
                )
            }
            else{
                Toasty.warning(view.context, AirportNotesApp.appContext.getString(R.string.no_internet_add_note), Toast.LENGTH_LONG, true).show()
            }
        }
        builder = this.context?.let { AlertDialog.Builder(it) }!!
        view.findViewById<Button>(R.id.filterByBtn).setOnClickListener{ view ->
            val dialog: AlertDialog = builder.create()
            dialog.show()
        }

        val callback = object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                //TODO "Dialog kapanmadan , navigationı durdurmanın yolunu bul"
                val note = view.findViewById<EditText>(R.id.noteText)
                if(note.text.isNotEmpty()){
                    if( viewModel.draftNote.value != null){
                        val draft = viewModel.draftNote.value!!
                        val yesNoBuilder =AlertDialog.Builder(activity as MainActivity)
                        yesNoBuilder?.setMessage(getString(R.string.do_u_want_to_keep_your_draft))
                            ?.setPositiveButton(getString(R.string.yes_keep_it_please)
                            ) { _, _ ->
                                draft.Text = note.text.toString()
                                viewModel.updateDraftNote(draft)

                            }?.setNegativeButton(getString(R.string.no_delete_it_please)
                            ) { _, _ ->
                                viewModel.deleteDraft(airportID!!)
                                viewModel.deleteNotification()

                            }
                        yesNoBuilder?.setCancelable(false)
                        yesNoBuilder?.create()?.show()
                    }
                    else{
                        val yesNoBuilder = AlertDialog.Builder(activity as MainActivity)
                        yesNoBuilder?.setMessage(getString(R.string.do_you_want_to_save_your_note_as_draft))
                            ?.setPositiveButton(getString(R.string.yes_save_it_please)
                            ) { _, _ ->
                                val noteText = view.findViewById<EditText>(R.id.noteText)
                                var lang = ""
                                if(viewModel.filteredLang.value != null) {
                                    lang = viewModel.filteredLang.value!!.Code
                                }
                                viewModel.addNoteDraft(noteText.text.toString(), airportID!!, lang)
                            }?.setNegativeButton(getString(R.string.no_delete_it_please)
                            ) { _, _ ->

                            }
                        yesNoBuilder?.setCancelable(false)
                        yesNoBuilder?.create()?.show()
                    }
                }
                else{
                    if( viewModel.draftNote.value != null) {

                        val yesNoBuilder = AlertDialog.Builder(activity as MainActivity)
                        yesNoBuilder?.setMessage(getString(R.string.do_u_want_to_keep_your_draft))
                            ?.setPositiveButton(getString(R.string.yes_keep_it_please)
                            ) { _, _ ->

                            }?.setNegativeButton(getString(R.string.no_delete_it_please)
                            ) { _, _ ->
                                viewModel.deleteDraft(airportID!!)
                                viewModel.deleteNotification()

                            }
                        yesNoBuilder?.setCancelable(false)
                        yesNoBuilder?.create()?.show()
                    }
                }
            }
        }
        requireActivity().onBackPressedDispatcher.addCallback(this, callback)

        observeViewModel(view)
        return view
    }

    private fun observeViewModel(view: View?) {
        viewModel.languages.observe(viewLifecycleOwner, Observer { languages ->
            languages?.let {
                val list = ArrayList<String>()
                for (l in languages){
                    list.add(l.Title)
                }
                builder.setTitle(getString(R.string.choose_a_language))?.setItems(list.toTypedArray(),
                    DialogInterface.OnClickListener { dialog, which ->
                        viewModel.filteredLang.value = languages[which]
                        if(languages[which].Title != "All") {
                            val lang = languages[which].Title
                            val yesNoBuilder = AlertDialog.Builder(activity as MainActivity)
                            yesNoBuilder?.setMessage(resources.getString(R.string.ask_for_preferred_lang, lang))
                                ?.setPositiveButton(getString(R.string.yes_please)
                                ) { _, _ ->
                                    AppPreferences.preferredLanguage = languages[which].Code
                                }?.setNegativeButton(getString(R.string.no_i_dont_want)
                                ) { _, _ ->
                                    // User cancelled the dialog
                                }
                            yesNoBuilder?.create()?.show()
                        }
                        // Create the AlertDialog object and return it
                    })
            }
        })

        viewModel.filteredLang.observe(viewLifecycleOwner, Observer{lang ->
            lang?.let {
                view?.findViewById<Button>(R.id.filterByBtn)?.text = getString(R.string.selected_language, lang.Title)
            }
        })
        viewModel.draftNote.observe(viewLifecycleOwner, Observer{note ->
            note?.let {
                val text = view?.findViewById<EditText>(R.id.noteText)
                text?.setText(note.Text)
            }
        })
        viewModel.addResult.observe(viewLifecycleOwner, Observer{result ->
            result?.let {

            }

        })
    }

}

Я прочитал десятки страниц об этом и попробовал большую часть, но не смог найти решение .

1 Ответ

0 голосов
/ 05 апреля 2020

Я понял, что неправильно вызвал функцию onOptionsItemSelected в MainActivity, вызвав это. Аналогичная проблема возникла в меню параметров, чтобы я мог найти причину.

Вот неправильная версия

 override fun onOptionsItemSelected(menuItem: MenuItem?): Boolean {
        if (menuItem != null) {
            onBackPressedDispatcher.onBackPressed()
        }
        return super.onOptionsItemSelected(menuItem)
    }

А вот правильная версия

override fun onOptionsItemSelected(menuItem: MenuItem?): Boolean {
    val id = menuItem?.itemId
    if (id == android.R.id.home) {
        onBackPressedDispatcher.onBackPressed()
        return true
    }
    return super.onOptionsItemSelected(menuItem)
}
...