Skip to content

Simple one-liner ViewBinding in Fragments and Activities with Kotlin 🍄 Simplify usage of Android View Binding with Kotlin Property Delegates and solve behavior of Fragment’s ViewLifecycleOwner 🌱 ViewBindingPropertyDelegate

License

Notifications You must be signed in to change notification settings

Kotlin-Android-Open-Source/ViewBindingDelegate

 
 

Repository files navigation

ViewBindingDelegate

  • Simplify usage of Android View Binding with Kotlin Property Delegates and solve behavior of Fragment’s ViewLifecycleOwner.
  • Simple one-liner ViewBinding in Fragments and Activities with Kotlin.
  • Lightweight and simple library.

Month Week Android Tests Android build CI Jitpack GitHub ktlint Kotlin API Hits

Medium article

Read ViewBinding Delegate — one line to get details about implementation.

Getting Started

1. Add the JitPack repository to your build file

Add it in your root build.gradle at the end of repositories:

  • Kotlin
allprojects { repositories { ... maven(url = "https://jitpack.io") } }
  • Groovy
allprojects { repositories { ... maven { url 'https://jitpack.io' } } }

2. Add the dependency

dependencies { implementation("com.github.hoc081098:ViewBindingDelegate:1.3.1") }

3. Enable ViewBinding

https://developer.android.com/topic/libraries/view-binding#setup

Usage

import com.hoc081098.viewbindingdelegate.*

1. Activity (with reflection). See example

Click to expand
class MainActivity : AppCompatActivity(R.layout.activity_main) { private val viewBinding by viewBinding<ActivityMainBinding>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) viewBinding.button.setOnClickListener { startActivity(Intent(this@MainActivity, SecondActivity::class.java)) } } }

2. Activity (without reflection): Pass ::bind method reference. See example

Click to expand
class SecondActivity : AppCompatActivity(R.layout.activity_second) { private val binding by viewBinding(ActivitySecondBinding::bind) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding.root } }

3. Fragment (with reflection). See example

Click to expand
class FirstFragment : Fragment(R.layout.fragment_first) { private val binding by viewBinding<FragmentFirstBinding> { button.setOnClickListener(null) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.button.setOnClickListener { findNavController().navigate(R.id.actionFirstFragmentToSecondFragment) } } }

4. Fragment (without reflection): Pass ::bind method reference. See example

Click to expand
class SecondFragment : Fragment(R.layout.fragment_second) { private val binding by viewBinding(FragmentSecondBinding::bind) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.root } }

5. Includes <merge/> tag layout: Create 2 ViewBinding property. See example

Click to expand
class ThirdFragment : Fragment(R.layout.fragment_third) { private val includeBinding by viewBinding<FragmentThirdIncludeBinding>() private val binding by viewBinding<FragmentThirdBinding> { buttonThird.setOnClickListener(null) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) includeBinding.textViewThirdInclude.text = "Working..." binding.buttonThird.setOnClickListener { Toast.makeText(requireContext(), "Clicked", Toast.LENGTH_SHORT).show() } } }

6. The Dialog of DialogFragmentSee example

Extends DefaultViewBindingDialogFragment or implements ViewBindingDialogFragment.

Click to expand
class DemoDialogFragment : DefaultViewBindingDialogFragment() { private val viewBinding by dialogFragmentViewBinding(R.id.root, DialogFragmentDemoBinding::bind) private val viewBinding2 by dialogFragmentViewBinding<DialogFragmentDemoBinding>(R.id.root) override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { return AlertDialog.Builder(requireContext()) .setTitle("Demo dialog") .setNegativeButton("Cancel") { _, _ -> } .setPositiveButton("OK") { _, _ -> } .setView(R.layout.dialog_fragment_demo) .create() } override fun onResume() { super.onResume() viewBinding.textInputLayout viewBinding2.textInputLayout } }

7. inflateViewBinding extension methods on ViewGroup/LayoutInflater/Context. See example

Can be used in RecyclerView.Adapter # onCreateViewHolder to easily create a RecyclerView.ViewHolder with a ViewBinding.

Click to expand
import com.hoc081098.viewbindingdelegate.inflateViewBinding class DemoAdapter : ListAdapter<String, DemoAdapter.VH>(...) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = VH(parent inflateViewBinding false) override fun onBindViewHolder(holder: VH, position: Int) = holder.bind(getItem(position)) class VH(private val binding: ItemRecyclerBinding) : RecyclerView.ViewHolder(binding.root) { fun bind(item: String) { ... } } }

Note

1. Activity

Must setContentView before access ViewBinding property. This can be done easily with constructor:

public AppCompatActivity(@LayoutRes int contentLayoutId) { ... }
class MainActivity : AppCompatActivity(R.layout.activity_main) { ... }

2. Fragment

Fragment's View must be not null before access ViewBinding property. This can be done easily with constructor:

public Fragment(@LayoutRes int contentLayoutId) { ... }
class FirstFragment : Fragment(R.layout.fragment_first) { ... }

3. Proguard

If there is any problem with Proguard, add below to your app/proguard-rules.pro:

# ViewBindingDelegate uses Reflection. -keepclassmembers class ** implements androidx.viewbinding.ViewBinding { public static ** bind(android.view.View); public static ** inflate(android.view.LayoutInflater, android.view.ViewGroup, boolean); public static ** inflate(android.view.LayoutInflater, android.view.ViewGroup); } 

4. Throws IllegalStateException: "Attempt to get view binding when fragment view is destroyed" when accessing delegate property in onDestroyView

Since version 1.0.0-alpha03 - Feb 16, 2021, we cannot access ViewBinding delegate property in onDestroyView (this causes many problems). Recommended way is passing a lambda to onDestroyView: (T.() -> Unit)? = null parameter of extension functions, eg.

- private val binding by viewBinding<FragmentFirstBinding>() + private val binding by viewBinding<FragmentFirstBinding> { /*this: FragmentFirstBinding*/ + button.setOnClickListener(null) + recyclerView.adapter = null + } override fun onDestroyView() { super.onDestroyView() - binding.button.setOnClickListener(null) - binding.recyclerView.adapter = null }

5. Min SDK version

Since version 1.2.0, minSdkVersion has been changed to 14.

License

MIT License Copyright (c) 2020-2021 Petrus Nguyễn Thái Học 

About

Simple one-liner ViewBinding in Fragments and Activities with Kotlin 🍄 Simplify usage of Android View Binding with Kotlin Property Delegates and solve behavior of Fragment’s ViewLifecycleOwner 🌱 ViewBindingPropertyDelegate

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Kotlin 100.0%