【问题标题】:Listener not implemented when inflating dialog-Android膨胀对话框时未实现侦听器-Android
【发布时间】:2022-01-21 00:39:43
【问题描述】:

我正在尝试在“CreateShoppingListMenuFragment”中添加自定义对话框成功,也许是相关的?

这是错误信息:

logo1200.shoppinglist, PID: 24194
java.lang.ClassCastException: com.camilogo1200.shoppinglist.presentation.MainActivity@11852bbmust implement ShoppingListNameRequestListener
    at com.camilogo1200.shoppinglist.presentation.fragments.ShoppingListNameRequestDialog.onAttach(ShoppinListNameRequestDialog.kt:68)
    at androidx.fragment.app.Fragment.performAttach(Fragment.java:2922)
    at androidx.fragment.app.FragmentStateManager.attach(FragmentStateManager.java:464)
    at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:275)
    at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)

这是我的 DialogFragment:

class ShoppingListNameRequestDialog : DialogFragment() {

private lateinit var listener: ShoppingListNameRequestListener



override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return activity?.let {
        val builder = AlertDialog.Builder(it)
        val inflater: LayoutInflater = requireActivity().layoutInflater
        val requestNameView = inflater.inflate(R.layout.shopping_list_name_request_dialog, null)
        val nameInput = requestNameView.findViewById<TextView>(R.id.shopping_list_dialog_input)
        var listName = ""

        builder.setView(requestNameView)
            .setPositiveButton(R.string.save_shopping_list,
                DialogInterface.OnClickListener {dialog, id ->

                    if(nameInput.text.toString() != "")
                       listName = nameInput.text.toString()
                       listener.onDialogPositiveClick(this,listName);

                })
            .setNegativeButton(R.string.cancel,
                DialogInterface.OnClickListener{dialog, id ->
                    listener.onDialogNegativeClick(this)
                })

        builder.create()
    } ?: throw IllegalStateException("Activity cannot be null")
}


interface ShoppingListNameRequestListener {
    fun onDialogPositiveClick(dialog: DialogFragment,listName:String)
    fun onDialogNegativeClick(dialog: DialogFragment)
}


override fun onAttach(context: Context) {
    super.onAttach(context)
   
    try {
       
        listener = context as ShoppingListNameRequestListener
    } catch (e: ClassCastException) {
       
        throw ClassCastException((context.toString() +
                "must implement ShoppingListNameRequestListener"))
    }
}

这是我的“CreateShoppingListMenuFragment”(我正在填充对话框的主机片段):

class CreateShoppingListMenuFragment : Fragment(),
ShoppingListNameRequestDialog.ShoppingListNameRequestListener {

private lateinit var binding: FragmentCreateShoppingListMenuBinding
private val viewModel: CreateShoppingListMenuViewModel by activityViewModels()
private val args: CreateShoppingListMenuFragmentArgs by navArgs()

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    binding = DataBindingUtil.inflate(
        layoutInflater,
        R.layout.fragment_create_shopping_list_menu,
        container,
        false
    )

    binding.lifecycleOwner = this

    viewModel.createItems()

    viewModel.viewState.observe(viewLifecycleOwner, ::handleViewState)

    val login = args.ownerName
    val listId = args.listId

    viewModel.setOwnerAndList(login, listId)

    binding.createItemButton.setOnClickListener {
        val directionToFragment =
            CreateShoppingListMenuFragmentDirections.actionCreateShoppingListMenuFragmentToCreateItemMenuFragment(
                login,
                listId
            )
        Navigation.findNavController(binding.root).navigate(directionToFragment)
    }

    binding.completeShoppingListButton.setOnClickListener {
        showNoticeDialog()
    }

    return binding.root
}

private fun showNoticeDialog() {

    val dialog = ShoppingListNameRequestDialog()
    dialog.show(parentFragmentManager, "ShoppingListNameRequestDialog")
}


override fun onDialogPositiveClick(dialog: DialogFragment,listName: String) {
    val result = viewModel.saveShoppingList(listName)
    Log.i("shoppingListResult", "$result")
    // travel to final fragment sent shoppinglist as arg
}

override fun onDialogNegativeClick(dialog: DialogFragment) {
    // User touched the dialog's negative button
}


private fun handleViewState(viewState: CreateShoppingListMenuViewState) {
    when (viewState) {
        is CreateShoppingListMenuViewState.ErrorViewState -> showError(viewState.exception as ShoppingException)
        //is RegisterViewState.SuccessViewState ->showSuccess()
        else -> showSuccess(viewState)
    }
}


private fun showSuccess(viewState: CreateShoppingListMenuViewState) {
    val receivedList = viewState as CreateShoppingListMenuViewState.SuccessViewState
    val dataList = receivedList.data

    val adapter = ShoppingListMenuAdapter(dataList, viewModel::changeItemCount)


    binding.itemListArray.adapter = adapter
}


private fun showError(exception: ShoppingException) {

    if (exception.idError as? ItemError == ItemError.NO_ITEMS_CREATED) {
        val message = getString(R.string.no_items_created_error_messages)
        Toast.makeText(activity, message, Toast.LENGTH_LONG).show()
    }

任何帮助将不胜感激!

【问题讨论】:

    标签: android dialog dialogfragment


    【解决方案1】:

    onAttach(Context context) 中的 Context 是上下文 Activity 片段没有自己的 Context 。 这里的问题是您将上下文转换为 ShoppingListNameRequestListener 以使您的 Activity 需要实现侦听器。

    解决这个问题有几种方法。如果我们采用您的方法,我们可以将片段实例作为 targetFragment 传递,并将其用作 DialogFragment 内的侦听器。

    private fun showNoticeDialog() {
        val dialog = ShoppingListNameRequestDialog()
        dialog.setTargetFragment(this)
        dialog.show(parentFragmentManager, "ShoppingListNameRequestDialog")
    }
    

    然后在对话框中你可以做这样的事情。

    class ShoppingListNameRequestDialog:DialogFragment(){
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            targetFragment?.let {
                listener = it as ShoppingListNameRequestListener
            }
        }
    }
    

    但是setTargetFragment 现在已被弃用。作为替代方式,您可以使用共享的ViewModel 或使用新的 API FragmentResultListener 执行相同操作。

    【讨论】:

    • ADM 感谢您的快速答复!我研究了 FragmentResultListener 并且我了解它在发回信息时使用。从我的 dialogFragment 中,肯定比我做的更简洁和更容易,但是我仍然不明白如何实现它来膨胀对话框,因为我知道需要 dialog.show() 来做这件事,并且上下文是需要,我该怎么做?
    • 好吧,现在我无法为您提供代码。所以here you go。我认为这是最好的方法。这很容易。试试看吧..
    猜你喜欢
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-27
    • 1970-01-01
    • 2017-12-19
    • 2011-11-30
    相关资源
    最近更新 更多