Karan Sharma
Karan Sharma

Reputation: 2619

How to inflate a ViewStub using ViewBinding in Android

As Kotlin Synthetics is deprecated, we are migrating to ViewBinding.

I have tried a lot of googling and reading documentation on ViewStub, ViewBinding and have implemented ViewBinding for Fragments Activities, include, merge tags however I could not find any way to inflate the ViewStub using ViewBinding.

 <ViewStub
            android:id="@+id/viewStubLayout"
            tools:layout="@layout/view_demo_layout" />

Please ignore the width and height attributes for this they were added as a style and have been removed from this snippet.

Can you please share how to inflate this view with another xml layout dynamically using ViewBinding.

Even in the ViewStub.java file, the class level comments state that,

The preferred way to perform the inflation of the layout resource is the following:

ViewStub stub = findViewById(R.id.stub);
View inflated = stub.inflate(); 

Does this mean that, I have to keep using R.layout.xxx_xx to inflate the viewstub. Can't I use the binding object for that particular xml file to inflate the view ?

Upvotes: 11

Views: 10766

Answers (3)

Somesh Kumar
Somesh Kumar

Reputation: 8638

I wrote about ViewBinding when it was in Beta. I covered every case except ViewStub. ViewStub case is fairly similar to the case of <Include> in my linked article. What you have to do is call bind() function of your ViewStub layout and pass the root where you added ViewStub. Remember to call bind() in setOnInflateListener.

class MainFragment : Fragment() {
private var binding: FragmentMainBinding by autoCleared()
private var stubBinding: StubBinding by autoCleared()

  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
      binding = FragmentMainBinding.inflate(inflater, container, false)
      binding.stub.setOnInflateListener { _, inflateId -> stubBinding = StubBinding.bind(inflateId) }
      return binding.root
  }

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
      super.onViewCreated(view, savedInstanceState)
      binding.stub.inflate()
      stubBinding.tvTestMe.text = "Hurray"
   }
}

Upvotes: 13

Rohit
Rohit

Reputation: 2681

It can be done via 2 simple lines

binding.viewStub.layoutResource = R.layout.layoutId
binding.viewStub.inflate()

Upvotes: -1

Saikrishna Rajaraman
Saikrishna Rajaraman

Reputation: 3273

One small correction in @Somesh's answer

The inflated view which is passed to the StubBinding is wrong. We should actually pass the view which we receive from the onInflate listener

class MainFragment : Fragment() {
private var binding: FragmentMainBinding by autoCleared()
private var stubBinding: StubBinding by autoCleared()

  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
      binding = FragmentMainBinding.inflate(inflater, container, false)
      binding.stub.setOnInflateListener { _, inflated -> stubBinding = StubBinding.bind(inflated) }
      return binding.root
  }

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
      super.onViewCreated(view, savedInstanceState)
      binding.stub.inflate()
      stubBinding.tvTestMe.text = "Hurray"
   }
}

Upvotes: 4

Related Questions