Kolejnym krokiem na ścieżce rozwoju biblioteki będzie zaprojektowanie malutkiego API, oraz dodanie obsługi kolorów do poszczególnych elementów, które pojawią się w widoku kartki z kalendarza.
Projektowanie zaczniemy od atrybutów, które dodamy w pliku xml. Będą one miały także swoją reprezentację w javie, przez klasyczne gettery i settery. Atrybutami tymi będą kolory, a mianowicie:
- barColor
- textColor
- cardBackgroundColor
- borderColor
Tak naprawdę nie wyobrażam sobie, żeby zmieniać któryś z tych kolorów po za kolorem paska, ale API wystawię, biblioteka będzie malutka, ale przynajmniej z szerokimi możliwościami konfiguracji. Aby zdefiniować parametry xmlowe utworzyłem plik attrs.xml w folderze values biblioteki. W pliku tym zdefiniowałem styl o nazwie takiej samej jak aplikacja (to nie jest obligatoryjne), oraz parametry xml, z których będzie można skorzystać. Kodzik
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="DayView">
<attr name="barColor" format="color" />
<attr name="textColor" format="color" />
<attr name="cardBackgroundColor" format="color" />
<attr name="borderColor" format="color" />
</declare-styleable>
</resources>
Po zbudowaniu aplikacji możemy już dodać te parametry do dema, ale nic z tego nie wyniknie. Dlatego najpierw obsłużymy je w klasie biblioteki:
var barColor = -12627531
var textColor = -16777216
var cardBackgroundColor = -1
var borderColor = -2302756
var date = Date()
constructor(ctx: Context) : super(ctx)
Więc tak, co tu się dzieje? Do góry mamy deklarację zmiennych (słówko kluczowe var), brak modyfikatora dostępu oznacza w Kotlinie public. W javie chcielibyśmy mieć takie jaki pola prywatne i modyfikatory dostępu do tego. W Kotlinie pola prywatne znaczy dostępne tylko w klasie z której korzystają, a pola publiczne mają już gettery i settery tworzone domyślnie. Przy czym, podobnie jak w C# możemy sobie zmodyfikować metody gettera i settera. Czyli, sama definicja zmiennych wystawia nam całe potrzebne API. Którego użycie w Kotlinie będzie wyglądało tak
dayView.date = Date()
Z kolei w javie automagicznie pojawi nam się odpowiedni setter
private void test() {
DayView dayView = new DayView(null, null);
dayView.setDate(new Date());
}
Prawda, że fajne?
Wrócę jeszcze do tego, co dzieje się w konstruktorze tego widoku:
constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) {
val a = context.theme.obtainStyledAttributes(
attrs,
R.styleable.DayView,
0, 0)
val typedValue = TypedValue()
val theme = context.theme
try {
if (theme.resolveAttribute(R.attr.colorPrimary, typedValue, true))
barColor = typedValue.data
barColor = a.getColor(R.styleable.DayView_barColor, barColor)
textColor = a.getColor(R.styleable.DayView_textColor, textColor)
cardBackgroundColor = a.getColor(R.styleable.DayView_cardBackgroundColor, cardBackgroundColor)
borderColor = a.getColor(R.styleable.DayView_borderColor, borderColor)
} finally {
a.recycle()
}
Zmienna a zawiera parametry, które udało się pobrać z xmla. W instrukcji try najpierw sprawdzamy, czy została zdefiniowana zmienna o nazwie colorPrimary. Jeśli tak, to barColor zamiast cyferek które tam ustawiłem przyjmuję tą wartość. Dalej następuje próba odczytania barColoru z konfiguracji widoku w pliku xml. Jeśli to się nie uda, zostaje domyślny kolor (drugi parametr). Podobnie z pozostałymi kolorami.
Reasumując udało się stworzyć konfigurację, której można użyć w pliku xml, wczytać ją do kodu, oraz wystawić API. Całkiem nieźle, jak na te kilka linii kodu. Wszystko zaccomitowane jako „collors and api”. Na następny raz czeka już prawdopodobnie namalowanie tej biblioteki.
Comments are closed.
Nazwa zmiennej jako 'a’ jakoś mi strasznie przeszkadza. Wychodzę z założenia że nazwy zmiennych powinny mówić czym są, a to dużo nie mówi. Wiem że nie ma tu jakiejś zakręconej logiki, ale IMHO i tak powinno się nazywać sensownie 🙂
Zastanawiałem się nad tym, ale w dokumentacji jest tak samo 😉
https://developer.android.com/training/custom-views/create-view.html#customattr