使用Kotlin 1.20.20(不重要,旧版本的行为相同)
当布局位于单独的库模块中时,Android Studio在查找和引用视图时没有问题
import kotlinx.android.synthetic.main.view_user_input.*
但是当我尝试编译应用时,Unresolved reference: view_user_input
上的:app:compileDebugKotlin
失败了。
在库模块中引用视图时,一切正常。
我在这里错过了什么吗?
添加项目结构。所有模块都使用kotlin和kotlin扩展。
build.gradle
app/
build.gradle //main application
library-module-a/
build.gradle //library application
library-module-b/
build.gradle //library application
中已注册的问题
答案 0 :(得分:6)
一种解决方法是创建一个“别名”属性,该属性可以从其他模块中使用:
// SyntheticExports.kt
package com.example.synthetic.exported
import kotlinx.android.synthetic.main.layout_in_library.*
inline val Activity.exported_text_view get() = text_view
然后在另一个模块上:
// MainActivity.kt
import com.example.synthetic.exported.exported_text_view
exported_text_view.text = "example"
对我们有用。必须为view
,fragment
等创建不同的扩展名。必须手动进行扩展有点繁琐,但这是我们找到的最简单的解决方法。
附加:这也是一种将合成扩展导出为公共库的一部分的好方法,而不仅仅是在内部模块中。
答案 1 :(得分:3)
以上答案均未对我有帮助。 将这两个插件添加到库模块顶部的build.gradle文件中:
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android'
这应该可以解决问题。
答案 2 :(得分:2)
您可以尝试切换到1.2.30-eap-16
并添加
androidExtensions {
experimental = true
}
到build.gradle
。
答案 3 :(得分:2)
我也遇到了这个问题,我的解决方法是:
请勿使用import kotlinx.android.synthetic.main .... *
使用findViewById()
例如:textview_id.text =“ abc”。我将其更改为findViewById(R.id.textview_id).text =“ abc”
答案 4 :(得分:1)
如@cesards上面评论中所述,这是an on going issue与Kotlin Android扩展。直到今天仍未解决。
我的主要建议是将视图和相关行为封装为自定义视图,而不是通过<include>
标签将其包括在内,而应将其直接用作布局<com.example.app.YourCustomView>
。
无论您的视图类是否在另一个模块中,这都将起作用。
但是,如果您只想从包含的视图中获得一个参考,我发现了一个解决方法。
按照以下步骤将kotlin合成导入用于其他模块中包含的布局:
我不确定这是如何工作以及为什么起作用,但这是一种非常脆弱和肮脏的重用布局方式。
您的包含布局(fragment_example.xml)
<include
android:id="@+id/exampleView"
layout="@layout/example_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>
您的片段类(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
}
答案 5 :(得分:1)
该解决方案比想象的要简单得多,Kotlin合成糖是Kotlin Android扩展的一部分,您只需要手动应用插件(Android Studio会自动将此插件仅应用于应用程序模块):
将以下内容添加到库/功能模块的构建Gradle中:
apply plugin: 'kotlin-android-extensions'
现在,以您的Kotlin代码享受Kotlin合成糖! ;)
答案 6 :(得分:0)
请勿导入以下库import kotlinx.android.synthetic.main.my_view.view.*
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)
}
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
来源:
答案 7 :(得分:0)
我的情况是::我需要子类(应用模块)中的基类(来自lib)视图引用,并且具有来自库模块的基类的视图引用最少。
我会说,这是一种解决方法,而不是解决方案。
解决方案1 从基类获取视图引用
//lib module snippet
import kotlinx.android.synthetic.main.view_user_input.*
class LibModuleBaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.view_user_input)
}
protected val vFirstName: TextView by lazy { tvFirstName }
...........
}
//app module snippet
class AppModuleActivity : LibModuleBaseActivity() {
fun setUserDetails(name: String) {
vFirstName.text = name
}
}
解决方案2 通过基本类完成任务
//lib module snippet
import kotlinx.android.synthetic.main.view_user_input.*
class LibModuleBaseActivity : AppCompatActivity() {
protected fun setUserDetails(name: String) {
tvFirstName.text = name
}
...........
}
//app module snippet
class AppModuleActivity : LibModuleBaseActivity() {
............
setUserDetails("user_name")
}
注意:仅当您从lib模块继承并且您的Base类正在放大视图时,此方法才有效。
答案 8 :(得分:0)
在上述@pablisco解决方案的逐步改进中,我的库中有一个文件:
// SyntheticExports.kt
@file:Suppress("ClassName")
package com.example.library.synthetic.main
import android.view.TextView
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.common_layout.view.rootLayout as syntheticRootLayout
import kotlinx.android.synthetic.main.common_layout.view.retryButton as syntheticRetryButton
object common_layout {
object view {
inline val View.rootLayout: ViewGroup get() = syntheticRootLayout
inline val View.retryButton: TextView get() = syntheticRetryButton
}
}
然后在另一个模块上:
// MainActivity.kt
import com.example.library.synthetic.main.common_layout.view.rootLayout
import com.example.library.synthetic.main.common_layout.view.retryButton
rootView.rootLayout.isVisible = true
rootView.retryButton.setOnClickListener { doIt() }
如果此问题已解决,我只需要更改导入以“ kotlinx.android”开头,而不是“ comp.example.library”即可。
答案 9 :(得分:-1)
我通过将androidExtension和buildscript从项目build.gradle复制到使用该库的模块,解决了我的问题。
A = JOIN X by (j1) left outer, Y by (j1);
SPLIT A into B (IF Y::j1 IS NULL), C otherwise;
D = FOREACH B GENERATE X::j2;
注意:我使用以下版本的kotlin和gradle:
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
}