Reputation: 4702
With the deprecation of kotlin synthetics
I faced the problem, that I can not access some standard layouts from my base class
anymore. For example, I have a base class for three fragments and in all of them, there is a button. My old approach was to get the button in the base class with synthetics and then assign some default clicklistener etc.
My question is: What would be the best approach to migrate from the synthetics to viewbinding / databinding here? Another question I am asking my self is, how could I access the view_layouts outside the activity / fragment now?
abstract class BaseRebuildFragment(layout: Int) : Fragment(layout) {
abstract val nextFragment: NavDirections
abstract val baseViewModel: ViewModel
open val dataOverViewFragment: Boolean = false
@Inject @RebuildProgressDescription lateinit var progressBarDescription: ArrayList<String>
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initAppStandardToolbar()
initStateProgressBar(progressBarDescription)
initButton()
hideBottomNav()
}
private fun initButton() {
calibrate_btn_next.setOnClickListener { // not working anymore
if (dataOverViewFragment) return@setOnClickListener else if (this.validForm()) findNavController().navigate(nextFragment)
}
}
open fun validForm(): Boolean { return false }
}
@AndroidEntryPoint
class RebuildOptionFragment : BaseRebuildFragment(R.layout.fragment_rebuild_option) {
override val baseViewModel: RebuildViewModel by navGraphViewModels(R.id.nav_send_rebuild) { defaultViewModelProviderFactory }
private val rebuildBinding: FragmentRebuildOptionBinding by viewBinding()
override val nextFragment: NavDirections = RebuildOptionFragmentDirections.actionRebuildOptionFragmentToRebuildUserDataFragment()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
bindObjects()
baseViewModel.setStateEvent(RebuildStateEvent.GetPrice)
subscribeRebuildListObserver()
}
private fun bindObjects() = with(rebuildBinding) {
viewModel = baseViewModel
lifecycleOwner = viewLifecycleOwner
lendingListener = LendingSwitch()
}
override fun validForm(): Boolean = baseViewModel.shippingValidator.isShippingOptionsValid()
}
fun Fragment.initStateProgressBar(progressBarDescription: ArrayList<String>) = with(app_standard_progress_bar) { // not working anymore
setStateDescriptionData(progressBarDescription)
}
fun Fragment.initAppStandardToolbar() {
toolbar.setupWithNavController(findNavController(), AppBarConfiguration(findNavController().graph)) // not working anymore
}
Upvotes: 1
Views: 1025
Reputation: 81539
For dynamic views accessed without any certainty of type safety, you can use findViewById
as you normally would have.
To access the view in a Fragment, you can use requireView()
.
Upvotes: 0
Reputation: 93551
findViewById
can be used directly instead of using synthetics to accomplish the same thing, but without type safety. You have to provide the type since it won't be able to infer the type.
fun Fragment.initStateProgressBar(progressBarDescription: ArrayList<String>) = with(requireView().findViewById<ProgressBar>(R.id.app_standard_progress_bar)) {
setStateDescriptionData(progressBarDescription)
}
Upvotes: 1
Reputation: 19524
With view binding you're meant to inflate the layout yourself using the generated binding class - so for R.layout.fragment_rebuild_option
it should be FragmentRebuildOptionBinding
.
In onCreateView
, call the inflate
option on that class:
binding = FragmentRebuildOptionBinding.inflate(inflater, container, false)
// return the root layout view
return binding.root
That creates a binding object that has all your View
references as properties, like you get with synthetics - so things like binding.calibrate_btn_next
. That means binding
needs to be a member variable in your Fragment
class, so all your functions can access it.
Then it's basically just a case of changing all your code to refer to binding.whatever
instead of just whatever
Upvotes: 1