2016-02-26 10 views
6

Anko docs powiedz nam, jak dodać niestandardowe widoki do DSL. Ale jeśli mój widok niestandardowy jest grupą widoku, pojawiają się problemy.Jak dodać niestandardowe grupy widoków do DSL Anko?

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

ale jeśli zmienię myFrameLayout inwokację do frameLayout działa OK. Jaki jest więc właściwy sposób na tworzenie grup widoków z wykorzystaniem funkcji Anko DSL?

Odpowiedz

0

Jeśli przyjrzymy się źródłom Anko, zobaczymy, że frameLayout rzeczywiście zwraca instancję klasy _FrameLayout, gdzie zdefiniowane są te funkcje lparams. W moim rozumieniu jest to potrzebne, więc te funkcje lparams są dostępne tylko w kodzie budującym układ.

W pliku Anko Layouts.kt dostępne są następujące klasy _<ViewGroup> dla każdego obsługiwanego ViewGroup.

Prostym sposobem na obsługę niestandardowej grupy widoków jest utworzenie klasy _<ViewGroup> z implementacją metod lparams. Problem polega na tym, że ta klasa _<ViewGroup> często zawiera znacznie więcej kodu niż mój <ViewGroup> sam w sobie!

A jeśli chcę utworzyć wiele niestandardowych grup widoków, dodanie do nich obsługi Anko staje się dużym problemem z tym podejściem. Załóżmy, że mam klasy MyFrameLayout1, MyFrameLayout2, . Są w zasadzie FrameLayout, więc chcę, aby te same parametry układu były z nimi używane. Ale muszę utworzyć klasy _FrameLayout1, _FrameLayout2, , , które są po prostu kopiowaniem/wklejaniem Anko's _FrameLayout.

Więc trochę poprawiłem to podejście.Tworzę interface _FrameLayout:

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

i teraz wspierać wszelkie niestandardowe FrameLayout podklasę Muszę tylko:

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

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

Zmniejsza kopiuj/wklej dużo, podczas tworzenia wielu grup zwyczaj oglądać.

+0

Złożyłem problem dotyczący tego https://github.com/Kotlin/anko/issues/152 – netimen

0

Jeśli pójdziesz do dowolnego lparams deklaracji ANKO z kodu, można zobaczyć, że wewnątrz Anko wygenerowany kod DSL lparams jest funkcja rozszerzenie dla T: View który wygląda następująco:

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() 
    [email protected] = layoutParams 
    return this 
} 

(i więcej przeciążenia dla różnych konstruktorów LayoutParams)

Jest zadeklarowany wewnątrz klasy, więc jest widoczny tylko w funkcjach z odbiornikiem tej klasy, patrz another question o tej metodzie programowania DSL.


Aby móc korzystać lparams dla własnych ViewGroup w Anko DSL, trzeba zadeklarować podobną funkcję lub funkcje wewnątrz kodu niestandardowy widok, który stworzy odpowiedni LayoutParams dla swojej klasy.

Jeśli chcesz również ukryć lparams funkcji spoza DSL, można dokonać podklasę swojej MyFrameLayout i używać go tylko w kodzie DSL, współpracując z MyFrameLayout się gdzie indziej.

Po tym można zadzwonić pod numer lparams na dowolne View wewnątrz lambda, które można przekazać jako init: MyFrameLayout.() -> Unit do fun ViewManager.myFrameLayout.

3

Właściwie wystarczy przedłużyć ANKO i deklarują swoją CustomView następnie używać go w DSL normalnie:

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

następnie używać go w DSL normalnie

frameLayout { 
    customView() 
} 
2

jeśli dziedziczą np _RelativeLayout zamiast RelativeLayout można użyć niestandardowego układu, jak można się spodziewać.

Powiązane problemy