21

I have a following layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@android:color/white"
    android:paddingLeft="20dp"
    android:paddingRight="20dp">

    <TextView
        android:id="@+id/tvErrorTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:textColor="@android:color/background_dark"
        android:textSize="18sp"
        />
    <TextView
        android:id="@+id/tvErrorDesc"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:textColor="@android:color/darker_gray"
        android:textSize="16sp"
        />
    <TextView
        android:id="@+id/tvAction"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:layout_marginBottom="10dp"
        android:layout_gravity="end"
        android:padding="5dp"
        android:textSize="15sp"
        android:textStyle="bold"
        android:textAllCaps="true"
        android:textColor="@android:color/holo_purple"
        />
</LinearLayout>

When I want to use [kotlin android extensions][1] outside of activity like below, it doesn't work. I ended up doing findViewById.

...
...
import kotlinx.android.synthetic.main.dialog_error.*
...
...
 val view = LayoutInflater.from(context).inflate(R.layout.dialog_error, null, false)
    val tvErrorTitle = view.findViewById(R.id.tvErrorTitle) as TextView
    val tvErrorDesc = view.findViewById(R.id.tvErrorDesc) as TextView
    val tvErrorAction = view.findViewById(R.id.tvAction) as TextView

It doesn't pull the views directly from xml. How to use it in programmatically inflated layout and avoid findViewById?

Note : This question strictly belongs to [Kotlin Android Extensions][1], not the language itself.

Edit I have imported both :

import kotlinx.android.synthetic.main.dialog_error.view.*
import kotlinx.android.synthetic.main.dialog_error.*

But Android Studio still tries to import from R.id and doesn't recognize those two imports. Is there anything missing? [1]: https://kotlinlang.org/docs/tutorials/android-plugin.html

Lino
  • 5,084
  • 3
  • 21
  • 39
Krupal Shah
  • 8,949
  • 11
  • 57
  • 93

4 Answers4

46

From the docs you linked:

If we want to call the synthetic properties on View (useful in adapter classes), we should also import

kotlinx.android.synthetic.main.activity_main.view.*.

That is, import kotlinx.android.synthetic.main.layout.view.* as well to load the View extension properties.

Then:

val view = LayoutInflater.from(context).inflate(...)
view.tvErrorTitle.text = "test"
nhaarman
  • 98,571
  • 55
  • 246
  • 278
7

It returns a view inflated:

layoutInflater.inflate(R.layout.your_layout, null)

See, you can replace this LayoutInflater.from(context) with this layoutInflater when your class extend from a Context superclass

Lucas B.
  • 489
  • 5
  • 15
  • 1
    This helped me. I followed the official android tutorial on DialogFragment, to a T. I kept getting a crash with error located at four lines, repeating indefinitely, seemingly rooted at Fragment.getLayoutInflater(). This fixed it. Not sure why it's not in the tutorial. (I would make a question of my problem and this solution but SO is bs and won't let me ask anymore questions.) – Prime624 Jan 11 '19 at 04:42
2

In kotlin you can try this to inflate layout inside linear layout using databinding

val inflater: LayoutInflater = LayoutInflater.from(activity).context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater

 val mBindingDeno: LayoutDenominationBinding =
        DataBindingUtil.inflate(
            inflater, R.layout.layout_denomination, null, false
        )
layout.addView(mBindingDeno.root)

Here layout is your LinearLayout

            <ScrollView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:fillViewport="true"
                android:nestedScrollingEnabled="true"
                android:visibility="gone">

                <LinearLayout
                    android:id="@+id/linear_denomination"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="vertical" />


            </ScrollView>
Arjun Othayoth
  • 351
  • 3
  • 5
0

Migrate from Kotlin synthetics to Jetpack view binding:

Kotlin Android Extensions is deprecated, which means that using Kotlin synthetics for view binding is no longer supported. If your app uses Kotlin synthetics for view binding, use this guide to migrate to Jetpack view binding.

If your app does not already use Kotlin synthetics for view binding, see View binding for basic usage information.

Like Android Extensions, Jetpack view binding is enabled on a module by module basis. For each module that uses view binding, set the viewBinding build option to true in the module-level build.gradle file:

android {
    ...
    buildFeatures {
        viewBinding true
    }
}

Use view binding in activities

To set up an instance of the binding class for use with an activity, perform the following steps in the activity's onCreate() method:

Call the static inflate() method included in the generated binding class. This creates an instance of the binding class for the activity to use. Get a reference to the root view by either calling the getRoot() method or using Kotlin property syntax.

Pass the root view to setContentView() to make it the active view on the screen.

private lateinit var binding: ResultProfileBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ResultProfileBinding.inflate(layoutInflater)
    val view = binding.root
    setContentView(view)
}

You can now use the instance of the binding class to reference any of the views:

binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }

For more information: https://developer.android.com/topic/libraries/view-binding#activities

Halil Ozel
  • 2,482
  • 3
  • 17
  • 32