7

我读到使用 Anko 的最大好处是它的可重用性。但我找不到它的确切例子。

目前在新的Android布局系统中,样板如下:

DrawerLayout (with some setup)
   CoordinatorLayout (with some setup)
      AppBarLayout (with some setup)
         ToolBar
      <The Main Content>
   NavigationView (with header inflated)

从上面的布局结构来看,只有<The Main Content>varry。在许多情况下,这些仪式设置几乎在每项活动中都重复。

因此,我在这里与 Anko 一起思考是否有关于该问题的可重用解决方案。我不希望它可重复用于通用布局,但至少我可以最小化项目中的仪式代码。也许我需要类似的东西:

class MainUI: AnkoComponent<MainActivity> {
  override fun createView(ui: AnkoContext<MainActivity>): View{
     return with(ui) {
        myCustomRootLayout {
           //here is what <The Main Content> will be
        }
     }
  }
}

从上面的代码中,我期望myCustomRootLayout将为根布局进行所有仪式设置,例如(DrawerLayout、CoordinatorLayout 等)。

那可能吗?

编辑 所以我认为我的问题是:如何制作可以托管其他组件的自定义组件

4

2 回答 2

4

重用代码的一种方法是简单地提取myCustomRootLayout到扩展方法中,如下所示:

class MainUI: AnkoComponent<MainActivity> {
    override fun createView(ui: AnkoContext<MainActivity>): View {
        return with(ui) {
            myCustomRootLayout {
               recyclerView()
            }
        }
    }
}

fun <T> AnkoContext<T>.myCustomRootLayout(customize: AnkoContext<T>.() -> Unit = {}): View {
    return relativeLayout {
        button("Hello")
        textView("myFriend")
        customize()
    }
}

但是,如文档中所述

尽管您可以直接使用 DSL(在onCreate()其他地方或其他地方),而无需创建任何额外的类,但在单独的类中拥有 UI 通常很方便。如果您使用提供的 AnkoComponent 接口,您还可以免费获得 DSL 布局预览功能。

将可重复使用的部分提取到单独的部分似乎是个好主意AnkoComponent

class MainUI : AnkoComponent<MainActivity> {
    override fun createView(ui: AnkoContext<MainActivity>): View {
        return with(ui) {
            MyCustomRootLayout<MainActivity>({
                recyclerView()
            }).createView(ui)
        }
    }
}


class MyCustomRootLayout<T : Context>(val customize: AnkoContext<T>.() -> Unit = {}) : AnkoComponent<T> {
    override fun createView(ui: AnkoContext<T>) = with(ui) {
        relativeLayout {
            button("Hello")
            textView("myFriend")
            customize()
        }
    }
}
于 2016-10-17T04:47:15.530 回答
3

我实际上找到了一种方法来做到这一点,花了我一段时间才弄清楚。

我在这里有一个非常基本的测试布局,内容被添加到 RelativeLayout.

这里的关键是将您的自定义布局添加AnkoContext到委托给直接父级(RelativeLayout在我的情况下)的委托中。

abstract class BaseAnkoComponent<T> : AnkoComponent<T> {

    companion object {
        val TOOLBAR_ID = View.generateViewId()
        val COLLAPSING_ID = View.generateViewId()
        val COORDINATOR_ID = View.generateViewId()
        val APPBAR_ID = View.generateViewId()
        val CONTENT_ID = View.generateViewId()
    }

    abstract fun <T> AnkoContext<T>.content(ui: AnkoContext<T>): View?

    override fun createView(ui: AnkoContext<T>) = with(ui) {
        coordinatorLayout {
            id = COORDINATOR_ID
            lparams(matchParent, matchParent)
            appBarLayout(R.style.AppTheme_AppBarOverlay) {
                id = APPBAR_ID
                lparams(matchParent, wrapContent)
                fitsSystemWindows = true
                collapsingToolbarLayout {
                    id = COLLAPSING_ID
                    val collapsingToolbarLayoutParams = AppBarLayout.LayoutParams(matchParent, matchParent)
                    collapsingToolbarLayoutParams.scrollFlags = AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL or AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS
                    layoutParams = collapsingToolbarLayoutParams
                    isTitleEnabled = false
                    toolbar {
                        id = TOOLBAR_ID
                        val toolbarLayoutParams = CollapsingToolbarLayout.LayoutParams(matchParent, dimenAttr(R.attr.actionBarSize))
                        toolbarLayoutParams.collapseMode = CollapsingToolbarLayout.LayoutParams.COLLAPSE_MODE_PIN
                        layoutParams = toolbarLayoutParams
                        minimumHeight = dimenAttr(R.attr.actionBarSize)
                        background = ColorDrawable(colorAttr(R.attr.colorPrimary))
                        popupTheme = R.style.AppTheme_PopupOverlay
                    }
                }
            }
            with(AnkoContext.createDelegate(relativeLayout {
                id = CONTENT_ID
                val relativeLayoutParams = CoordinatorLayout.LayoutParams(matchParent, matchParent)
                relativeLayoutParams.behavior = AppBarLayout.ScrollingViewBehavior()
                layoutParams = relativeLayoutParams
            })) {
                content(ui)
            }
        }
    }
}

然后您可以BaseAnkoComponent使用 Anko DSL 以同样的方式扩展和构建您的内容。

class FooActivityUi : BaseAnkoComponent<FooActivity>() {
  override fun <T> AnkoContext<T>.content(): View? {
    return verticalLayout {
      lparams(width = matchParent, height = matchParent)
      button("Hello")
      textView("myFriend")
    }
  }
}

我确信有更好的方法可以做到这一点,但我还没有找到。对 Kotlin 和 Anko 来说有点陌生。

于 2017-03-17T12:33:53.947 回答