Aug*_*rmo 5 android android-custom-view kotlin
我以那个小项目为例:
主活动.kt
package com.example.scratch
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
Run Code Online (Sandbox Code Playgroud)
布局/activity_main.xml
<?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">
<com.example.scratch.CustomViewWithContent
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
Run Code Online (Sandbox Code Playgroud)
CustomViewWithContainer.kt
package com.example.scratch
import android.content.Context
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.widget.FrameLayout
import androidx.constraintlayout.widget.ConstraintLayout
open class CustomViewWithContainer : ConstraintLayout {
private val contentContainer by lazy {
findViewById<FrameLayout>(R.id.content_container)
}
constructor(context: Context?) : super(context) {
commonInit(context)
}
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
commonInit(context)
}
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
) {
commonInit(context)
}
protected open fun commonInit(context: Context?) {
if (context == null) {
return
}
inflate(context, R.layout.custom_view_with_container, this)
if (isInEditMode) {
return
}
}
protected fun setContent(contentView: View) {
contentContainer.removeAllViews()
contentContainer.addView(contentView)
(contentView.layoutParams as FrameLayout.LayoutParams).gravity = Gravity.CENTER
}
}
Run Code Online (Sandbox Code Playgroud)
布局/custom_view_content.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is a text view" />
</FrameLayout>
Run Code Online (Sandbox Code Playgroud)
CustomViewWithContent.kt
package com.example.scratch
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.widget.TextView
class CustomViewWithContent : CustomViewWithContainer {
private lateinit var contentView: View
private val textView by lazy {
contentView.findViewById<TextView>(R.id.text_view)
}
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
override fun commonInit(context: Context?) {
super.commonInit(context)
if (context == null) {
return
}
contentView = inflate(context, R.layout.custom_view_content, null)
if (isInEditMode) {
return
}
setContent(contentView)
Log.d(
CustomViewWithContent::class.java.simpleName,
"TextView id: ${textView.id}"
)
}
}
Run Code Online (Sandbox Code Playgroud)
布局/custom_view_with_container
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
<FrameLayout
android:id="@+id/content_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</merge>
Run Code Online (Sandbox Code Playgroud)
我不知道为什么它会崩溃。我正在获取的视图的 ID 与可以在布局中找到的 ID 完全相同.xml。
我很想知道懒惰返回null而不是视图本身的原因,因为它没有意义:/
通过那个gif,我们可以看到:
textView(这是 a lazy val)被认为是空的;notNullTextView不为空,它运行在惰性 val 初始化块中找到的相同代码text view;textView在IDE的Watches中运行相同的初始化代码,它也返回null。findViewById事实上,你的问题根本不相关。你可以将你的懒惰替换为
private val textView by lazy {
TextView(contentView.context)
}
Run Code Online (Sandbox Code Playgroud)
你会得到同样的错误!我认为这与lazy实现以及将未完全创建的对象传递给它然后尝试调用这一事实有关。不幸的是,我不能说到底错在哪里。
您可以轻松修复崩溃,lateinit例如:
class CustomViewWithContent : CustomViewWithContainer {
private lateinit var contentView: View
private lateinit var textView: TextView
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
override fun commonInit(context: Context?) {
super.commonInit(context)
if (context == null) {
return
}
contentView = inflate(context, R.layout.custom_view_content, null)
textView = contentView.findViewById(R.id.text_view)
if (isInEditMode) {
return
}
setContent(contentView)
Log.d(
CustomViewWithContent::class.java.simpleName,
"TextView id: ${textView.id}"
)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
722 次 |
| 最近记录: |