Search code examples
androidkotlinkotlin-android-extensionskotlin-extension

Kotlin synthetic extension for view


I have a layout with some views, one of them has the id title_whalemare

import kotlinx.android.synthetic.main.controller_settings.*
import kotlinx.android.synthetic.main.view_double_text.*

class MainSettingsController : BaseMvpController<MvpView, MvpPresenter>() {

    val title: TextView = title_whalemare

    override fun getLayout(): Int {
        return R.layout.controller_settings
    }
}

I try find it with kotlin extensions, but I can't because I get the following error

None of the following candidates is applicable because of receiver type mismatch None of the following candidates is applicable because of receiver type mismatch

controller_settings.xml

<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">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/title_whalemare"/>

</LinearLayout>

Where is my mistake?


Solution

  • Edit: synthetics are now deprecated and will be removed. Please see this blog post for details.


    What the error is trying to tell you is that you can only access views with Extensions from either within an Activity or a Fragment. This is because it does the exact same thing to find the views with the given IDs as what you'd be doing manually, it just calls Activity.findViewById() and Fragment.getView().findViewById(), and then does the type cast to the specific subclass of View. I'm guessing that your Controller is not an Activity or Fragment.

    There's another way to use Extensions, if you can pass in the root view of your layout to your controller somehow. Then you could do the following:

    val title: TextView = rootView.title_whalemare
    

    Again, this is just replacing the View.findViewById() call and the type cast.