Как работать с элементами макета сцены в Android

#android #xml #kotlin

Вопрос:

У меня есть несколько макетов с другой структурой, которые я использую в качестве макетов сцен, и у меня есть родительский макет, где я хочу загрузить их с различными переходами.

Родительский макет выглядит следующим образом

 <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@ id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@ id/root_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include layout="@layout/scene_1"/>
    </FrameLayout>
</FrameLayout>
 

scene_1 Выглядит это примерно так

 <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@ id/wall">

    <ImageView
        android:id="@ id/image_background"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/background"
        android:adjustViewBounds="true"
        android:scaleType="centerCrop" />

    <ImageView
        android:id="@ id/image_foreground"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:src="@drawable/foreground"
        android:adjustViewBounds="true"
        android:scaleType="centerCrop" />

</FrameLayout>
 

Затем, когда приходит какой-то обратный вызов с сервера, я хочу изменить сцену на scene_2, которая выглядит так:

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black"
    android:orientation="vertical"
    android:layout_gravity="center"
    android:gravity="center"
    android:id="@ id/wall2">

    <ProgressBar
        android:id="@ id/pb_wall2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@ id/wall2_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:textColor="@color/white"
        android:text="Some text"/>

    <Button
        android:id="@ id/btn_do_smth"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textColor="@color/white"
        android:text="Do Smth"/>

    <Button
        android:id="@ id/btn_go_back"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textColor="@color/white"
        android:text="Go back"/>

</LinearLayout>
 

I want to be able to set visibility property of progress bar, text view and buttons, as well as set listeners to buttons and so on. I do following for this purposes in my Activity file:

 ...
    private fun initWall2View() {
        wall2View = findViewById(R.id.wall2)
        pbWall2 = findViewById(R.id.pb_wall2)
        wall2Text = findViewById(R.id.wall2_text)
        btnDoSmth = findViewById(R.id.btn_do_smth)
        btnGoBack = findViewById(R.id.btn_go_back)

        val initWall2ViewScene = Scene(rootScene, wall2View as ViewGroup)
        TransitionManager.go(initWall2ViewScene, AutoTransition())

        myViewModel.wall2State.observe(this) { wall2State ->
            wall2State?.let {
                when (it) {
                    MyViewModel.Wall2State.Loading -> {
                        wall2View.visibility = View.VISIBLE
                        pbWall2.visibility = View.VISIBLE
                        wall2Text.visibility = View.GONE
                        btnDoSmth.visibility = View.GONE
                        btnGoBack.visibility = View.GONE
                    }
                    MyViewModel.Wall2State.Show -> {
                        wall2View.visibility = View.VISIBLE
                        pbWall2.visibility = View.GONE
                        wall2Text.visibility = View.VISIBLE
                        btnDoSmth.visibility = View.VISIBLE
                        btnGoBack.visibility = View.VISIBLE
                    }
                    MyViewModel.Wall2State.Hide -> {
                        wall2View.visibility = View.GONE
                    }
                }
            }
        }
        btnDoSmth.setOnClickListener {
            ...
        }
        btnGoBack.setOnClickListener {
            myViewModel.onGoBackPressed()
        }
    }
...
 

Программа строится и запускается, но сразу после этого умирает из-за исключения: java.lang.NullPointerException: findViewById(R.id.wall2) must not be null
Я предполагаю, что это связано с тем, что после компиляции в xml-файле макета буквально нет элемента с таким идентификатором, но как это сделать правильно? Я не хочу, чтобы все сцены были в одном xml-файле, потому что у меня их много, и в том, что они отображаются в разных ситуациях, больше логики. Я надеюсь, что есть решение.