Get value from BottomSheetDialogFragment

2.5k Views Asked by At

i have a fragment (A), where 3 actions are available. When the user select one action, before doing that, i need to ask him the password he used to login. I would like to do that using BottomSheetDialogFragment, but i don't know how to make the fragment A to listen if the password entered is correct.

This is the code of the BottomSheetDialogFragment

class ConfirmPasswordBottomSheet : BottomSheetDialogFragment() {

    companion object {
        const val TAG = "ConfirmPasswordBottomSheet"
    }

    fun newInstance(): ConfirmPasswordBottomSheet {
        return ConfirmPasswordBottomSheet()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setStyle(STYLE_NORMAL, R.style.CartissimaSheetDialogTheme)
    }

    @Inject
    lateinit var sharedPreferences: SharedPreferences

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

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

        showKeyboard()

        confirm_pwd_btn.setOnClickListener {
            if(DesEncrypted().encrypt(confirm_pwd_edit.text.toString()) == ServiceUtils.getPassword(sharedPreferences)){

                }
            }else{
                with(requireActivity() as MainActivity) {
                    buildAlertMessageOneButton(
                        getString(R.string.common_warning),
                        getString(R.string.incorrect_password),
                        getString(R.string.common_close)
                    )
                }
            }
        }
    }
}

and this is the point in fragment A where i need to check the password (between the 2 if)

        show_pin_btn_float.setOnClickListener {

            if (with(activity as MainActivity) { checkCardPermission(PinOptionFragment.card.authorities[AuthoritiesCardEnum.CARTE_VIEW_PIN]!!) }) {
                if (card.driverPin) {
                    cardViewModel.requestPinDriver(with(activity as MainActivity) { currentUser.mainCode })
                } else {
                    cardViewModel.requestPin(card.pan)
                }
            }
        }
3

There are 3 best solutions below

1
On BEST ANSWER

You have to use an interface for this task. A simple use case for it is given below based on your code provided.

First create a listener in ConfirmPasswordBottomSheet like:

class ConfirmPasswordBottomSheet : BottomSheetDialogFragment() {

    private lateinit var listener: OnActionCompleteListener

    fun setOnActionCompleteListener(listener: OnActionCompleteListener) {
        this.listener = listener
    }
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        // your other code here
        confirm_pwd_btn.setOnClickListener {
            // pass the value of password here

            listener.onActionComplete("your password is this")
        }
    }

    // your other code here

    interface OnActionCompleteListener {
        fun onActionComplete(str: String)
    }

}

Then after creating an instance of ConfirmPasswordBottomSheet you have to invoke setOnActionCompleteListener() by passing an instance of OnActionCompleteListener.

Create an instance where you want to use it like below:

val listener = object: ConfirmPasswordBottomSheet.OnActionCompleteListener() {
    fun onActionComplete(str: String) {
        // do what you want to do here because this block will be invoked in bottom sheet
        // you will receive "your password is this" here
        // as per question maybe check your password / pin
        if (with(activity as MainActivity) { checkCardPermission(PinOptionFragment.card.authorities[AuthoritiesCardEnum.CARTE_VIEW_PIN]!!) }) {
            if (card.driverPin) {
                cardViewModel.requestPinDriver(with(activity as MainActivity) { currentUser.mainCode })
            } else {
                cardViewModel.requestPin(card.pan)
            }
        }
    }
}

After creating an instance of interface you have to set it to the ConfirmPasswordBottomSheet's instance in Fragment (A) like below:

val bottomSheet = ConfirmPasswordBottomSheet()
bottomSheet.setOnActionCompleteListener(listener)

NOTE: this code is untested and might need some modification because it is off the top of my head.

0
On

Use Interface with a method

public interface PasswordCheck {
 fun isSuccess(password : Boolean);
}

pass the interface in the bottom sheet constructor.

Then call it in your fragment like this :

val callback = object : PasswordCheck {
        override fun isSuccess(password : Boolean) {
             if(password){
               //do what you want
             }
        }
    }
0
On

Here is my solution, based greatly on Naveen Niraula's answer. In my case, I have a text field by clicking on which I can select some options from the bottom sheet dialog and then return (and insert) the selected item (string) to the text field.

Bottom sheet class

class MyBottomSheet(private val listener: OnClickListener) : BottomSheetDialogFragment() {

private val binding: LayoutBottomSheetBinding by viewBinding() // just a view binding library

fun interface OnClickListener {
    fun onItemSelected(item: String)
}

companion object {
    const val TAG = "MyBottomSheet"
}

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

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

    binding.buttonFirstOption.setOnClickListener {
        listener.onItemSelected(getString(R.string.bottom_sheet_option_first))
    }
    binding.buttonSecondOption.setOnClickListener {
        listener.onItemSelected(getString(R.string.bottom_sheet_option_second))
    }
}
}

Fragment class

class MyFragment : Fragment(R.layout.my_fragment) {

private val binding: FragmentMyBinding by viewBinding()

private lateinit var bottomSheet: MyBottomSheet


override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    
    binding.textInput.editText?.setOnClickListener {
        selectOptionFromDialog()
    }
}

private fun selectOptionFromDialog() {
    val listener =
        MyBottomSheet.OnClickListener { option ->
            binding.textInput.editText?.setText(option)
            bottomSheet.dismiss()
        }

    bottomSheet = MyBottomSheet(listener)
    bottomSheet.show(childFragmentManager, bottomSheet.tag)
}
}