How to dynamically use ViewBinding with nested activities on Android?

192 Views Asked by At

So I have this structure that I wanted to replace the working code with viewBinding instead of findViewById<>

abstract class ParentActivity: AppCompatActivity() 

class ChildActivity: ParentActivity() 

activity_parent.xml is a layout that contain a placeholder for a dynamically replaced child layout using setContentView override below:

So in ParentActivity.kt

abstract class ParentActivity : AppCompatActivity()
    override fun setContentView(layoutResID: Int) {
        val parent = LayoutInflater.from(this).inflate(R.layout.activity_parent, null)
        LayoutInflater.from(this).inflate(layoutResID, parent.findViewById(R.id.abstractViewContainer) as androidx.coordinatorlayout.widget.CoordinatorLayout, true)
        super.setContentView(parent)
    }
     
    // ... Shared code

}

activity_parent.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    tools:context=".nestedActivity.ParentActivity">

    <TextView
        android:id="@+id/parentTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello I am Parent Activity"
        />
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:id="@+id/abstractViewContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/parentTextView">

</LinearLayout>

ChildActivity.kt

class ChildActivity : ParentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_child)
    }
}

Is there a way to use ViewBinding instead of the old solution here?

This code is more than 10 years ago, today I would just use fragments and nav_graph (or just compose) but here I need to keep the nested activites architecture because of legacy implication of parent activity over thousands of other activites.

Solutions like this : https://stackoverflow.com/a/64461332/2474454 won't apply to my case, I want to fusion the ActivityParentBinding with ActivityChildBinding dynamically according to the child.

1

There are 1 best solutions below

0
On

Looks like that answer is close. I think all you need is a ViewGroup.addView().

How about the following. (Not sure if you really need the CoordinatorLayout from your example; could replace it with a FrameLayout if you don't need the extra support)

// Copyright 2023 Google LLC.
// SPDX-License-Identifier: Apache-2.0

abstract class ParentActivity : AppCompatActivity() {
    private lateinit var binding: ActivityParentBinding // for parent stuff

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityParentBinding.inflate(layoutInflater)
        binding.abstractViewContainer.addView(createContentView()) // add the child
        setContentView(binding.root)

        // ...
    }

    abstract fun createContentView(): View
}

class ChildActivity: ParentActivity() {
    private lateinit var binding: ActivityChildBinding // for child stuff

    override fun createContentView(): View {
        binding = ActivityChildBinding.inflate(layoutInflater)
        return binding.root
    }
}