Unresolved reference for synthetic view when layout is in library module

限于喜欢 提交于 2019-12-02 16:45:20

One way to solve this is to create an "alias" property that can be consumed from other modules:

// SyntheticExports.kt
package com.example.synthetic.exported

import kotlinx.android.synthetic.main.layout_in_library.*

inline val Activity.exported_text_view get() = text_view

Then on the other module:

// MainActivity.kt
import com.example.synthetic.exported.exported_text_view

exported_text_view.text = "example"

That works for us. Have to create different extensions for view, fragment, etc. It's a bit tedious to have to do them manually but this is the simplest workaround we found.

Extra: This is also a decent method to export synthetic extensions as part of a public library too, not just in an internal module.

I also got this issue and my solution is:

  • Don't use import kotlinx.android.synthetic.main....*

  • Use findViewById()

Ex: textview_id.text = "abc". I change it to findViewById(R.id.textview_id).text = "abc"

you could try switching to 1.2.30-eap-16 and adding

androidExtensions { experimental = true }

to your build.gradle.

As mentioned in the comment by @cesards above this is an on going issue with the Kotlin Android Extentions. And it is not solved as of today.


Good: Use Custom Views

My primary suggestion is encapsulating the view and the relevant behavior as a custom view and instead of including it via <include> tag, use it directly in your layout as <com.example.app.YourCustomView>.

This will work no matter your view class is in another module or not.


Bad and Ugly: Id Collision Workaround

However I found a hacky workaround if you only want to get one reference from the included view.

Follow these steps to use kotlin synthetic imports for the layouts included from other modules:

  1. Give an id to the view you want to get reference of in the included xml file.
  2. Give the same id to the include tag in the including xml file.
  3. Now synthetic import the view (id) from the including layout (not from the included)

I'm not really sure how and why this works but it's a very fragile and dirty way of reusing layouts.

Example:

Your including layout (fragment_example.xml)

<include
    android:id="@+id/exampleView"
    layout="@layout/example_layout" />

Your included layout (example_layout.xml)

<merge xmlns:android="http://schemas.android.com/apk/res/android">

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

</merge>

Your fragment class (ExampleFragment.kt)

import kotlinx.android.synthetic.main.fragment_example.exampleView

// Do not import the exampleView through example_layout.exampleView

class ExampleFragment : Fragment() {
    // Do something with imported exampleView
}

Preconditions

Do not import the following library import kotlinx.android.synthetic.main.my_view.view.*

app/MainActivity.kt

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val view: View = MyView(this)
        view.findViewById<TextView>(R.id.textViewPocLib).text = "I can edit the library components"
        setContentView(view)
}

my_library/MyView.kt

class MyView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
    LinearLayout(context, attrs, defStyleAttr) {

    init {
        LayoutInflater.from(context)
            .inflate(R.layout.my_view, this, true)
    }
}

GL

Sources:

I solved my issue with copy both androidExtension and buildscript from project build.gradle to module that uses the library.

buildscript {

    repositories {
        jcenter()
        google()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:$gradle_version"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

androidExtensions {
    experimental = true
}

Note: I use the following version of kotlin and gradle:

buildscript {
    ext.kotlin_version = '1.3.0'
    ext.gradle_version = '3.0.1'
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!