8

Anko 文档告诉我们如何将自定义视图添加到 DSL。但是如果我的自定义视图是一个视图组,就会出现问题。

class MyFrameLayout(context: Context) : FrameLayout(context)

fun ViewManager.myFrameLayout(init: MyFrameLayout.() -> Unit = {}) = ankoView({ MyFrameLayout(it) }, init)

class MyUI : AnkoComponent<Fragment> {
    override fun createView(ui: AnkoContext<Fragment>) = with(ui) {

        myFrameLayout {
            textView("hello").lparams { // error: Unresolved reference: lparams
                bottomMargin = dip(40)
            }
        }
    }
}

但是如果我将myFrameLayout调用更改为frameLayout它可以正常工作。那么让视图组与 Anko DSL 一起使用的正确方法是什么?

4

4 回答 4

6

实际上你只需要扩展 anko 并声明你的 customview 然后在 DSL 中正常使用它:

public inline fun ViewManager.customView() = customView {}
public inline fun ViewManager.customView(init: CustomView.() -> Unit) = ankoView({ CustomView(it) }, init)

然后在DSL中正常使用

frameLayout {
    customView()
}
于 2016-03-21T16:27:12.743 回答
2

如果您继承自 eg_RelativeLayout而不是RelativeLayout,您可以按照您的期望使用您的自定义布局。

于 2017-09-20T14:59:08.547 回答
0

如果我们看一下 Anko 的源代码,我们可以看到它实际上frameLayout返回了一个类的实例_FrameLayout,其中定义了这些lparams函数。据我了解,这是必需的,因此这些lparams功能仅在布局构建代码中可用。

在 Anko 的Layouts.kt文件中_<ViewGroup>,每个受支持的ViewGroup.

因此,支持自定义视图组的直接方法是创建一个_<ViewGroup>具有lparams方法实现的类。问题是这个_<ViewGroup>类通常包含比我<ViewGroup>自己更多的代码!

如果我想创建许多自定义视图组,使用这种方法为它们添加 Anko 支持会变得很痛苦。假设我有MyFrameLayout1, MyFrameLayout2,MyFrameLayout3类。它们基本上是FrameLayout's 所以我希望与它们一起使用相同的布局参数。但我必须创建只是复制/粘贴 Anko_FrameLayout1的._FrameLayout2_FrameLaoyt3_FrameLayout

所以我稍微改进了这个方法。我创建一个interface _FrameLayout

interface _FrameLayout {
    // copy/paste from Anko's _FrameLayout
}

现在要支持任何自定义FrameLayout子类,我只需要:

class _MyFrameLayout(ctx: Context) : MyFrameLayout(ctx), _FrameLayout

fun ViewManager.myFrameLayout(init: _MyFrameLayout.() -> Unit = {})= ankoView({ _MyFrameLayout(it) }, init) 

在创建许多自定义视图组时,这大大减少了复制/粘贴。

于 2016-03-01T14:42:53.103 回答
0

如果您lparams从代码中查看 Anko 的任何声明,您可以看到在 Anko 生成的 DSL 代码中,lparams有一个扩展函数,T: View如下所示:

fun <T: View> T.lparams(
        width: Int = android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
        height: Int = android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
        init: android.widget.FrameLayout.LayoutParams.() -> Unit = defaultInit
): T {
    val layoutParams = android.widget.FrameLayout.LayoutParams(width, height)
    layoutParams.init()
    this@lparams.layoutParams = layoutParams
    return this
}

(以及不同LayoutParams构造函数的更多重载)

它是在一个类中声明的,因此它仅在具有该类接收器的函数中可见,请参阅关于这种 DSL 编程方法的另一个问题。


为了能够在 Anko DSL 中lparams用于您的自定义ViewGroup,您必须在您的自定义视图代码中声明一个或多个类似的函数,这将为LayoutParams您的类创建一个合适的函数。

如果您还想lparams从 DSL 外部隐藏功能,您可以创建您的子类MyFrameLayout并仅在 DSL 代码中使用它,在MyFrameLayout其他地方使用它自己。

之后,您可以调用传递给的 lambda 内部的lparams任何内容。Viewinit: MyFrameLayout.() -> Unitfun ViewManager.myFrameLayout

于 2016-02-29T08:31:17.643 回答