如何在 Android 中使用接口作为监听器和 Dialog?

Posted

技术标签:

【中文标题】如何在 Android 中使用接口作为监听器和 Dialog?【英文标题】:How to use interfaces as listeners from and Dialoge in Android? 【发布时间】:2021-03-03 15:21:47 【问题描述】:

我不知道如何将 android 中的接口用作事件侦听器。我用方法onProfilePictureTaken定义了一个接口ProfilePictureTakenEvent。在通过单击片段的按钮打开的对话框中,用户可以使用相机拍摄图像。我使用了startActivityForResult的方法。我在片段中得到的这个动作的结果(图像)(被覆盖的方法onActivityResult)。

现在我的问题是:当我在片段中获得结果时,如何在对话框中显示这张图片?我以为我可以使用事件监听器,但我不知道怎么做也没有找到任何解释。

这是我的代码:

UserFragment.tk

class UserFragment() : Fragment() 
    private var userFragment: UserFragment? = null
    private var profilePictureTakenEvent: ProfilePictureTakenEvent? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? 
        return inflater.inflate(R.layout.fragment_user, container, false)
    

    override fun onViewCreated(
        view: View,
        savedInstanceState: Bundle?
    ) 
        super.onViewCreated(view, savedInstanceState)

        this.userFragment = this

        val database = UserManagerDatabase(view.context)
        val repository = UserRepository(database)
        val factory = UserViewModelFactory(repository)

        val viewModel = ViewModelProviders.of(this, factory).get(UserViewModel::class.java)
        val adapter = UserAdapter(listOf(), viewModel)

        rvUsers.layoutManager = LinearLayoutManager(view.context)
        rvUsers.adapter = adapter

        var emailAddresses: List<String> = emptyList()

        viewModel.getAll().observe(viewLifecycleOwner,  userList ->
            adapter.users = userList
            emailAddresses = userList.map  user -> user.email 

            adapter.notifyDataSetChanged()
        )

        viewModel.getEmailAddresses().observe(viewLifecycleOwner, emailAddresses = it )

        fBtnAddUser.setOnClickListener 
            AddUserDialog(view.context,
            object: UserCreateEvent 
                override fun onAddButtonClicked(user: User) 
                    viewModel.insert(user)
                
            , emailAddresses, userFragment).show()
        
    

    fun setProfilePictureTakenEvent(profilePictureTakenEvent: ProfilePictureTakenEvent) 
        this.profilePictureTakenEvent = profilePictureTakenEvent
    

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) 
        super.onActivityResult(requestCode, resultCode, data)

        if (requestCode == AddUserDialog.REQUEST_IMAGE_CAPTURE) 
            this.profilePictureTakenEvent?.onProfilePictureTaken(data)
        
    

AddUserDialog.kt:

class AddUserDialog(
    context: Context,
    private var userCreateEvents: UserCreateEvent,
    private var emails: List<String>,
    private var parentFragment: UserFragment?
) : AppCompatDialog(context), ProfilePictureTakenEvent 

    companion object 
        const val REQUEST_IMAGE_CAPTURE = 1
    

    private var imageData: Bitmap? = null

    override fun onProfilePictureTaken(data: Intent?) 
        this.ivProfilePicture.setImageBitmap(data?.extras?.get("data") as Bitmap)
    

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.dialog_add_user)
        setTitle(context.getString(R.string.title_add_user))

        val editTextViews: Map<String, EditText> = mapOf(
            "first_name"            to dAddUserEdFirstName,
            "last_name"             to dAddUserEdLastName,
            "email"                 to dAddUserEdEmail,
            "password"              to dAddUserEdPassword,
            "password_confirmation" to dAddUserEdPasswordConfirmation
        )

        dAddUserBtnSave.setOnClickListener 
            val firstName               = dAddUserEdFirstName.text.toString()
            val lastName                = dAddUserEdLastName.text.toString()
            val username                = "$firstName.toLowerCase(Locale.GERMAN)-$lastName.toLowerCase(Locale.GERMAN)"
            val email                   = dAddUserEdEmail.text.toString()
            val password                = dAddUserEdPassword.text.toString()
            val passwordConfirmation    = dAddUserEdPasswordConfirmation.text.toString()

            var error = false
            val emptyFields: StringBuilder = StringBuilder()

            // Check if any EditText is empty
            editTextViews.forEach (key, editTextView) ->
                val textEmpty: Boolean = editTextView.text.toString().isEmpty()

                if (textEmpty) 
                    error = true
                    emptyFields.append("$context.getString(AppHelper.stringTranslation(key)), ")
                

                AppHelper.updateBackground(context, editTextView, if (textEmpty) R.drawable.input_field_error else R.drawable.input_field)
            

            if (error) 
                //AppHelper.showToastLong(context, context.getString(R.string.error_field_not_filled, AppHelper.commaStringToCorrectGrammatical(context, emptyFields.toString())))
                return@setOnClickListener
            

            // Check if E-Mail address is valid
            if (AppHelper.invalidEmail(email)) 
                AppHelper.showToastShort(context, R.string.error_invalid_email)
                return@setOnClickListener
            

            // Check if supplied E-Mail address is unique
            if (emails.contains(email)) 
                AppHelper.showToastShort(context, R.string.error_email_already_taken)
                return@setOnClickListener
            

            // Check if password and password confirmation match
            if (password != passwordConfirmation) 
                AppHelper.showToastShort(context, R.string.error_password_confirmation_not_matching)
                return@setOnClickListener
            

            //TODO: Password hashing

            // Creating the User
            val user = User(firstName, lastName, username, email, password)
            userCreateEvents.onAddButtonClicked(user)

            // Closing the dialog after calling the onClickEvent and data is valid
            dismiss()
        

        btnTakeProfilePicture.setOnClickListener 
            val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)

            try 
                parentFragment?.startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
             catch (e: ActivityNotFoundException) 
                AppHelper.showToastLong(context, "Fehler")
            
        

        // Close dialog when cancel Button is clicked
        dAddUserBtnCancel.setOnClickListener  cancel() 
    


ProfilePictureTakenEvent.kt:

interface ProfilePictureTakenEvent 
    fun onProfilePictureTaken(data: Intent?)

【问题讨论】:

【参考方案1】:

据我了解,您的对话框在捕获图像后仍会显示, 就像从那个片段创建对话框一样,一个简单的解决方案可以是:将对象保存在一个全局变量中,可以调用一个函数来显示捕获的图像。 喜欢:

val dialog = AddUserDialog(....)

里面

onActivityResult(..)

...

dialog.updateImage(data)

因此实际上您不需要任何侦听器来在对话框中显示图像。

【讨论】:

这很简单,而且很有效。非常感谢!

以上是关于如何在 Android 中使用接口作为监听器和 Dialog?的主要内容,如果未能解决你的问题,请参考以下文章

Android 文本监听接口TextWatcher详解

android单例中的监听如何回调

如何使用接口android在适配器中创建onclick事件?

使用Android Jetpack导航时如何防止导航

Android进程间通信之内部类作为事件监听器

Android_基于监听的事件处理机制