У меня есть приложение 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 {
}
})
}
}
Я прочитал десятки страниц об этом и попробовал большую часть, но не смог найти решение .