Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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%

AltStyle によって変換されたページ (->オリジナル) /