2016-10-17 5 views
7

J'ai lu que le plus grand avantage d'utiliser Anko est sa réutilisabilité. Mais je n'ai pas trouvé son exemple exact.Est-il possible de réutiliser une mise en page dans Kotlin Anko

Actuellement dans le nouveau système de mise en page Android, la plaque de la chaudière est comme ci-dessous:

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

De la structure de mise en page ci-dessus, ne <The Main Content> est Varry. Et dans de nombreux cas, cette configuration cérémonielle dupliqué presque dans chaque activité.

Donc, ici, avec Anko, je pense qu'il existe une solution réutilisable à ce problème. Je ne m'attends pas à ce qu'il soit réutilisable pour la mise en page à usage général, mais au moins je peux minimiser le code de cérémonie dans le projet. Peut-être que je besoin de quelque chose comme:

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

À partir du code ci-dessus im attendant myCustomRootLayout fera toute la configuration d'apparat pour la mise en page des racines tels que (DrawerLayout, CoordinatorLayout etc etc).

Est-ce possible?

EDIT donc je pense que ma question est: Comment faire un composant personnalisé qui peut accueillir un autre composant

Répondre

3

Une façon de réutiliser le code est d'extraire simplement myCustomRootLayout dans une méthode d'extension comme ceci:

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() 
    } 
} 

Cependant, comme stated in the documentation:

Bien que vous puissiez utiliser le DSL directement (dans onCreate() ou partout ailleurs ), sans créer de classes supplémentaires, il est souvent pratique de avoir une interface utilisateur dans la classe séparée. Si vous utilisez l'interface AnkoComponent fournie, vous bénéficiez également d'une fonctionnalité de prévisualisation de disposition DSL gratuite.

Il semble être une bonne idée d'extraire la pièce réutilisable en AnkoComponent séparé:

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() 
     } 
    } 
} 
+0

merci de répondre.oui je comprends à ce sujet. mais pourrait trouver un exemple de la façon de faire un composant personnalisé qui est un conteneur de l'autre composant. Voir mon code, 'myCustomRootLayout' devrait contenir' DrawerLayout, CoordinatorLayout, AppBarLayout' etc etc, mais devrait également héberger un autre composant ''. Donc dans le futur je peux les utiliser comme: 'myCustomRootLayout {recyclerView()}' (en y ajoutant une vue recycleur) – ktutnik

+0

@ktutnik la méthode d'extension 'myCustomRootLayout' et la classe' MyCustomRootLayout' acceptent un délégué qui est invoqué après l'installation les éléments composants. Ce délégué peut être utilisé pour ajouter des éléments enfants personnalisés, c'est-à-dire 'recyclerView()' – miensol

+0

Je me soucie de la position de l'enfant inséré. Y a-t-il un effort à faire pour que les enfants soient les enfants de CoordinatorLayout par rapport à la vue racine? – ktutnik

3

j'ai trouvé une façon de faire, m'a pris un certain temps pour comprendre.

J'ai une disposition de test très basique ici, le contenu est ajouté à un RelativeLayout.

La clé ici est d'ajouter votre mise en page personnalisée dans un AnkoContext délégué qui délègue au parent immédiat (le RelativeLayout dans mon cas).

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) 
      } 
     } 
    } 
} 

Et vous pouvez étendre la BaseAnkoComponent et construire votre contenu de la même manière avec DSL Anko. Je suis sûr qu'il existe une meilleure façon de le faire, mais je ne l'ai pas trouvé. Kinda nouveau à Kotlin et Anko.