为什么从不调用 createView?

Why is createView never called?

我的最终目标是能够将我的内容小部件移动到自定义视图中,并在我的 MainView 的 Anko 布局中实例化该视图。我以为我曾经有过这个工作,但我无法重现它。

当我 运行 使用以下代码时,MainContextView createView 中的内容从不显示,我也从未看到消息 "creating main context view",但我 看到消息"main content view"。

我首先创建一个 MainContextView

class MainContextView(context: Context) : ViewGroup(context), AnkoComponent<Context> {

    lateinit var textBox: EditText
    lateinit var button: Button
    lateinit var clickCount: TextView

    override fun createView(ui: AnkoContext<Context>) = with(ui) {
        println("creating main context view")
        verticalLayout {
            themedEditText {
                hint = "hi from main context"
            }
            button = themedButton {
                text = "ok"
            }
            textBox = themedEditText {
                hint = "hi"
            }
            clickCount = themedTextView {
               text = "0"
            }
        }
    }

    override fun onLayout(p0: Boolean, p1: Int, p2: Int, p3: Int, p4: Int) {
        println("onLayout called")
    }

}

并从我的主视图调用它

class MainView : AnkoComponent<MainActivity> {

    lateinit var mainCtx: MainContextView
    lateinit var textBox: EditText
    lateinit var button: Button
    lateinit var clickCount: TextView
    lateinit var mainMenu: Menu
    lateinit var settingItem: MenuItem
    lateinit var otherItem: MenuItem
    lateinit var floatingActionButton: FloatingActionButton

    override fun createView(ui: AnkoContext<MainActivity>) = with(ui) {
        coordinatorLayout {
            verticalLayout {
                themedAppBarLayout {
                    themedToolbar(theme = R.style.Base_ThemeOverlay_AppCompat_Dark_ActionBar) {
                        title = resources.getString(R.string.app_name)
                        popupTheme = R.style.AppTheme
                        mainMenu = menu
                        settingItem = mainMenu.add("My Settings")
                        otherItem = mainMenu.add("My Other")
                    }
                }.lparams(width = matchParent, height = wrapContent)

                // ************************************
                // HERE IS THE CALL TO THE CONTEXT VIEW
                mainCtx = mainContextView { println("main content view ") }
               // *************************************

            }.lparams(width = matchParent, height = wrapContent) {
            }
            floatingActionButton = floatingActionButton {
                imageResource = android.R.drawable.ic_dialog_email
            }.lparams {
                margin = dip(10)
                gravity = Gravity.BOTTOM or Gravity.END
            }
        }
    }
}

MainView 被调用并设置为 MainActivity 的内容视图

class MainActivity : AppCompatActivity() {

    private lateinit var presenter: MainPresenter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val mainView = MainView()
        mainView.setContentView(this)
        presenter = MainPresenter(mainView)

    }

}

最后是 ViewManger 扩展

inline fun ViewManager.mainContextView(theme: Int = 0) = mainContextView(theme) {}

inline fun ViewManager.mainContextView(theme: Int = 0, init: MainContextView.() -> Unit): MainContextView {
    return ankoView({ MainContextView(it) }, theme, init)
}

我发现了我的问题,它与我的子视图有关,它被定义为 View/ViewGroup 的子 class,但没有真正实现任何方法。

事实证明这并不是真正正确的方向。该解决方案基于对此 issue

的评论

下面是解决方案的一些关键部分,我还创建了一个包含完整代码的 Gist

扩展函数,创建"SubView"实例class然后在ankoView()方法中调用createView()方法。它还将创建的实例传递到传递给扩展函数的闭包中,这是关键,因为它允许访问视图中包含的小部件。

inline fun ViewManager.mainContentView(theme: Int = 0) = mainContentView(theme) {}

inline fun ViewManager.mainContentView(theme: Int = 0, init: View.(mainContentView: MainContentView) -> Unit): View {
    val mainContentView = MainContentView()
    return ankoView({ mainContentView.createView(AnkoContext.create(it)) }, theme, { init(mainContentView)} )
}

"content view" 创建布局并保存对小部件的引用。

class MainContentView :  AnkoComponent<Context> {

    lateinit var textBox: EditText
    lateinit var button: Button
    lateinit var clickCount: TextView

    override fun createView(ui: AnkoContext<Context>) = with(ui) {
        verticalLayout {
            button = themedButton {
                text = "ok"
            }
            textBox = themedEditText {
                hint = "hi"
            }
            clickCount = themedTextView {
                text = "0"
            }
        }
    }
}

在主视图中,我有字段引用 "subView" 中的小部件,然后我在传递给 mainContentView 实例的闭包中对其进行初始化。

lateinit var textBox: EditText
lateinit var button: Button
lateinit var clickCount: TextView
private lateinit var mainMenu: Menu
lateinit var settingItem: MenuItem
lateinit var otherItem: MenuItem
private lateinit var floatingActionButton: FloatingActionButton


override fun createView(ui: AnkoContext<MainActivity>) = with(ui) {
    coordinatorLayout {
        verticalLayout {
            themedAppBarLayout {
                themedToolbar(theme = R.style.Base_ThemeOverlay_AppCompat_Dark_ActionBar) {
                    title = resources.getString(R.string.app_name)
                    popupTheme = R.style.AppTheme
                    mainMenu = menu
                    settingItem = mainMenu.add("My Settings")
                    otherItem = mainMenu.add("My Other")
                }
            }.lparams(width = matchParent, height = wrapContent)
            mainContentView {
                button = it.button
                textBox = it.textBox
                clickCount = it.clickCount
            }.lparams(width = matchParent, height = wrapContent)
        }.lparams(width = matchParent, height = wrapContent)
        floatingActionButton = floatingActionButton {
            imageResource = android.R.drawable.ic_dialog_email
        }.lparams {
            margin = dip(10)
            gravity = Gravity.BOTTOM or Gravity.END
        }
    }
}