Geรงen sene Google IO‘da duyurulduฤundan beri Compose‘u deneyimlemek to-do listimde bekleyen maddelerden biriydi. Yฤฑllar boyunca hep dinamik olarak view’i kodda yaratmak yerine xml’den inflate etmenin daha performanslฤฑ olduฤunu duyduk, รถlรงรผmledik, uyguladฤฑk, paylaลtฤฑk. UI’la ilgili konuลtuฤumuz konu genelde ConstraintLayout da รถncesine gidecek olursak, ne zaman LinearLayout ne zaman RelativeLayout kullanacaฤฤฑmฤฑzdฤฑ. Ne kadar iรง iรงe hiyararลi olursa eลit, ne noktada RelativeLayout daha performanslฤฑ รงalฤฑลฤฑr gibi konulardฤฑ. Ama iลin aรงฤฑkรงasฤฑ da UI geliลtirmek her Android geliลtiricisi tarafฤฑndan uygulamanฤฑn en keyifle geliลtirilen tarafฤฑ deฤildi. Kendi adฤฑma gรถrsel olarak รงฤฑktฤฑyฤฑ o an gรถrmek beni รงok etkilediฤi iรงin UI’dan hep keyif aldฤฑm. Biraz xml’in sevilmemesinden biraz da hep optimal bir performans รงฤฑktฤฑsฤฑ olan UI geliลtirebilmek iรงin ConstraintLayout ve UI Editor‘le tanฤฑลtฤฑk. Her ne kadar baลlarda UI Editor mรผkemmel รงalฤฑลmasa da zamanla รงok daha iyi bir noktaya geldi ve kolay bir ลekilde performanslฤฑ รงalฤฑลacak UI’ฤฑmฤฑzฤฑ geliลtirmeye baลladฤฑk. Compose’daysa Google ลimdiye kadar olan patternlardan รงok daha farklฤฑ bir ลekilde karลฤฑmฤฑza รงฤฑktฤฑ. Sadece Kotlin’le ve koddan geliลtirilen bir UI. ฤฐlk anons edildiฤinde Anko‘ya benzetildi, ancak Anko’yu da denemediฤim iรงin performans olarak xml’le karลฤฑlatฤฑrฤฑdฤฤฑmda nasฤฑl bir sonuรง elde ederiz bilmiyorum. O da ayrฤฑ bir blog, inceleme konusu olabilir.
developer.android‘e gรถre Compose’un resmi tanฤฑmฤฑ “Jetpack Compose is a modern toolkit for building native Android UI. Jetpack Compose simplifies and accelerates UI development on Android with less code, powerful tools, and intuitive Kotlin APIs.“. Aslฤฑnda tanฤฑmdan da anlaลฤฑlacaฤฤฑ gibi, yine herลeyin รงฤฑkฤฑล noktasฤฑ sadeleลme ve hฤฑzlanma. Compose geliลtirilirken React, Vue.js ve Flutter‘dan esinlenilmiล. Tabi bu arada en baลta sรถylemekte fayda var, Compose halen developer preview’de, รผretim ortamฤฑ iรงin รถnerilmiyor, herลeyi de yapabilir durumda deฤil, halen geliลtiriliyor. Compose’un xml’den farklฤฑ olduฤu bir nokta da declarative olmasฤฑ. Tรผrkรงe’ye รงevirdiฤimizde รงok anlamlฤฑ bir kelime olmuyor ama bunu Android hiyerarลisiyle ilgili iลleri delege ediyor gibi dรผลรผnebiliriz. UI’ฤฑn kullandฤฑฤฤฑ data gรผncellendiฤinde de otomatik olarak bu deฤiลiklik UI’a yansฤฑyor. Declarative vs Imperative konulu okuduฤum yazฤฑlardan en รงok sevdiฤimden de bir alฤฑntฤฑ yaparak biraz daha anlaลฤฑlabilir olmasฤฑnฤฑ saฤlamaya รงalฤฑลacaฤฤฑm. Declarative Programming bir arkadaลฤฑmฤฑzdan manzara fotoฤrafฤฑ รงizmesini istemek gibi. Ama arkadaลฤฑmฤฑzฤฑn nasฤฑl รงizdiฤiyle ilgilenmiyoruz, tamamen ona kalmฤฑล. Imperative Programming ise arkadaลฤฑmฤฑzฤฑn Bob Ross’dan nasฤฑl manzara รงizeceฤini dinlemesi ve beklenen sonucu almak iรงin Bob Ross’un verdiฤi step’leri adฤฑm adฤฑm takip ederek manzara fotoฤrafฤฑnฤฑ รงizmesi gibi tanฤฑmlanabilir.
Hadi nasฤฑl birลeyle karลฤฑlacaฤฤฑmฤฑzฤฑ gรถrelim, deneyelim artฤฑk. Google Codelabs altฤฑnda Compose Basics codelab’ini inceleyerek Compose’un nasฤฑl kullanฤฑlabileceฤi hakkฤฑnda temel bilgi sahibi olabilirsiniz. Compose’u deneyelimlemek iรงin Android Studio min version 4.0 olmasฤฑ gerekli, en iyi deneyimi almak iรงin ise son Canary Preview‘ฤฑ download edebilirsiniz. Bu versiyonu kurduฤunuzda ise proje templateleri altฤฑnda Compose’u da gรถrecekseniz. Basitรงe buradan bir hello world uygulamasฤฑ yaratฤฑp incelemeniz mรผmkรผn. Yine ayrฤฑca Google’ฤฑn code รถrneklerinde yer alan compose’la yazฤฑlmฤฑล olan Jetnews uygulamasฤฑnฤฑ incelemek de nasฤฑl bir yapฤฑ kurulacaฤฤฑ hakkฤฑnda daha detaylฤฑ bilgi verebilir.

UI as function: Compose’la UI fonksiyon olarak tanฤฑmlanฤฑr ve bu fonksiyon datayฤฑ view hiyerarลisine dรถnรผลtรผrรผr. Aลaฤฤฑdaki kod รถrneฤine bakarsak, input basit bir data parรงasฤฑ, isim; output ise bir text widget’ฤฑ. ฤฐsmi gรผncellemek istediฤimizde, fonksiyonu yeni datayla tekrar รงaฤฤฑrmak yeterli olacak, ui hiyerarลisi yeni bir textle text widget iรงermiล olacak. Kodu inflate etmek ve update etmek iรงin iki farklฤฑ kod bloฤuna da artฤฑk ihtiyacฤฑmฤฑz olmayacaฤฤฑ iรงin bu kodumuzu ciddi anlamda kฤฑsaltmฤฑล olacak. Eฤer bu kodu uygun bir isimle mesela “world” le รงaฤฤฑrฤฑrsak, รงalฤฑลtฤฑrdฤฑฤฤฑmฤฑzda ekranda “Hello world!” gรถreceฤiz.
@Composable | |
fun Greeting(name: String) { | |
Text (text = "Hello $name!") | |
} |
Yukarฤฑda template’den boล bir Compose kullanan boล bir Activity class oluลturabileceฤimizden bahsetmiลtim. Template’le oluลan Activity Class’ฤฑ aลaฤฤฑdaki gibi gรถrรผnecek. Bu ลekilde oluลturduฤumuzda ek birลey yapmadan Compose’u projemiz iรงerisinde kullanabiliyoruz, yani gradle dosyasฤฑnda dependency’si ekli ve Android Studio’nun Compose’la รงalฤฑลabilmesi iรงin gerekli olan buildFeatures { compose true} olarak set edilmiล olacak.
setContent bloฤu activity’nin layoutunu tanฤฑmlar. xml inflate etmek yerine burada composable function’ฤฑ รงaฤฤฑrฤฑyoruz. Jetpack Compose composable fonksiyonlarฤฑ uygulamanฤฑn UI elementlerine รงevirebilmek iรงin custom bir Kotlin compiler plugini kullanฤฑr. Mesela, Text() fonksiyonu Compose UI kรผtรผphanesinde tanฤฑmlฤฑdฤฑr, uygulamada bir text element tanฤฑmlamak iรงin bu fonksiyonu รงaฤฤฑrabiliriz.
Bir de daha รถnce Android Studio’da karลฤฑlamadฤฑฤฤฑmฤฑz yeni bir feature gรถrรผyoruz, default preview. @Preview’la annotate ettiฤimiz compose fonksiyonunu default preview kฤฑsmฤฑnda gรถrebiliriz. Bana da bu da biraz flutter’daki hot reload’ฤฑ anฤฑmsattฤฑ.

Peki az รถnce Composable Fonksiyon dedik, Composable Fonksiyon nedir dersek, Composable Fonksiyon @Composable ‘la annotate edilen bir fonskiyondur, sadece diฤer composable fonksiyonlarฤฑn scope’unda รงaฤrฤฑlabilir. Bu da bizim yazdฤฑฤฤฑmฤฑz Composable fonksiyonun diฤer @Composable fonksiyonlarฤฑ รงaฤฤฑrabilmesini saฤlar.
@Composable | |
fun Greeting(name: String) { | |
Text (text = "Hello $name!") | |
} |
Compose Single Responsibility Principle‘ฤฑ izler. @Composable fonksiyonlar sadece tek bir fonksiyonality’den sorumludur. Mesela aลaฤฤฑdaki รถrnekteki gibi bazฤฑ fonksiyonlara background vermek istersek Surface Composable fonksiyonunu kullanmamฤฑz gerekir. Baลka bir built-in componentle bunu yapamayฤฑz.
@Composable | |
fun Greeting(name: String) { | |
Surface(color = Color.Yellow){ | |
Text (text = "Hello $name!") | |
} | |
} |

Bu kodu emรผlatรถrde รงalฤฑลtฤฑrdฤฑฤฤฑmฤฑzda metin ekranฤฑn sol รผst tarafฤฑna yapฤฑลmฤฑล olacaktฤฑr. Nasฤฑl yaparฤฑz da view’lerin gรถrรผnรผmรผnรผ yerleลimini modifiye edebiliriz dediฤimizde ise Modifiers devreye giriyor.
Modifiers:
- Spacing/LayoutPadding
- AspectRatio
- Rows
- Column
Ben bu yazฤฑ iรงin compose’u denemeye baลladฤฑฤฤฑmda son version dev-03’tรผ. Sonra tekrar yeni bir proje aรงฤฑnca gรถrdรผm ki dev-04 gelmiล. Bugรผn android weekly’yi okurken bir yazฤฑda ise dev05’den dev06’ya geรงerken nelerin deฤiลtiฤini okudum. Dolayฤฑsฤฑyla yukardaki modifier isimlerinin denediฤinizde deฤiลmiล olabileceฤini bilmeli ve gรผncelini araลtฤฑrmalฤฑsฤฑnฤฑz.
En รงok kullanฤฑlan, alฤฑลฤฑk olunan รถzelliklerden biri olan margin dev03’te Spacing, dev04’te ise LayoutPadding olarak karลฤฑmฤฑza รงฤฑkฤฑyor. Aลaฤฤฑdaki kod รถrneฤinde de gรถrรผldรผฤรผ gibi text yaratฤฑlฤฑrken modifier’a verilerek padding elde edilebiliyor.
@Composable | |
fun Greeting(name: String) { | |
Text (text = "Hello $name!", modifier = Spacing(24.dp)) | |
} |

Row ve Column ise adฤฑndan anlaลฤฑlacaฤฤฑ รผzere yatayda ya da dikey dรผzlemde view’lerimizi yerleลtirmek iรงin kullanฤฑlฤฑyor. Column alt alta, Row ise yan yana dizilimi saฤlamฤฑล oluyor. Adeta LinearLayout’da horizontal ya da vertical kullanmฤฑลฤฑz gibi.
@Composable | |
fun SpeakerInformation(speaker: SpeakerInfo) { | |
Column( | |
modifier = Spacing(16.dp) | |
) { | |
Text(speaker.name) | |
Text(speaker.title) | |
Text(speaker.sessionTitle) | |
} | |
} |
Yukarฤฑdaki kod รถrneriฤini run ettiฤimizde ise aลaฤฤฑdaki ekranla karลฤฑlaลฤฑrฤฑz.

Peki diyelim ki uygulamamฤฑzda tรผm ortak konfigรผrasyonlara sahip bir container yaratmak istiyoruz. Generic bir container yapmak iรงin Composable fonksiyonumuzun Unit return eden bir Composable fonksiyonu parametre olarak almasฤฑ gerekmekte. Lambdalarฤฑ daha รถnce kullanmamฤฑล olanlar daha fazla bilgi iรงin linkten inceleyebilirler. Burada Unit dรถndรผrรผyoruz รงรผnkรผ farkettiฤiniz รผzere tรผm Composable fonksiyonlarฤฑn Unit dรถndรผrmesi gerekli.
Bu fonksiyon yazฤฑnฤฑn baลlarฤฑnda kullandฤฑฤฤฑmฤฑza eลdeฤer bir sonuรง รงฤฑkaracak ancak รงok daha flexible. Container fonksiyonlar okunabilirliฤi arttฤฑrmasฤฑ ve kodun reusable olmasฤฑna olanak saฤlamasฤฑ aรงฤฑsฤฑndan uygulanmasฤฑ iyi bir deneyimdir.
@Composable | |
fun IWDDemoApp(children: @Composable() () -> Unit) { | |
MaterialTheme(colors = lightThemeColors){ | |
children() | |
} | |
} |
Buradan bir baลka รงok kullanฤฑlan ihtiyaรงla devam edelim. Uygulamamฤฑza imaj ekleme. Bunu da DrawImage fonksiyonunu kullanarak yapฤฑyoruz.
@Composable | |
fun SpeakerInformation(speaker: SpeakerInfo) { | |
Column( | |
modifier = Spacing(16.dp) | |
) { | |
DrawImage(image = speaker.image) | |
Text(speaker.name) | |
Text(speaker.title) | |
Text(speaker.sessionTitle) | |
} | |
} |
Imaja herhangi bir kฤฑsฤฑtlama vermedik, run ettiฤimizde aลaฤฤฑdaki gibi gรถrรผntรผ elde etmiล oluyoruz.

ลimdi imajฤฑmฤฑz da var ancak tรผm view’i kapladฤฑ. Image isteฤimiz gibibir stil verebilmek iรงin Container‘ฤฑn iรงerisine koymalฤฑyฤฑz. Container’lar iรงerisindeki view’leri tutan ve diฤer UI elemenleriyle belli bir hizalaa yapmamฤฑzฤฑ saฤlayan general-purpose content objesidir. Bunu kenarda aklฤฑmฤฑzda tutmakta fayda var, geliลtireceฤimiz UI komplexleลtikรงe Container ihtiyacฤฑ da olacak. Container ekledikten sonra size ve position’ฤฑ uygulayabiliriz.
- Height: Container’ฤฑn boyunu belirtmek iรงindir. Height setting’i Expanded’dan daha รถnceliklidir, bu sebeple aลaฤฤฑdaki รถrnekte imajฤฑn boyu 180 DP olacak. Geniลlik ise parent’ฤฑnฤฑn verdiฤi maximum geniลlik olacak.
- Expanded: Container’ฤฑn size’ฤฑnฤฑ belirtir. Default deฤeri false’dur. (Container’ฤฑn boyutu iรงerisinde รงocuฤun boyutu kadar) Eฤer ki true yaparsak, size’ฤฑn parentฤฑ kadar olmasฤฑnฤฑ istediฤimizi belirtmiล oluruz.
@Composable | |
fun SpeakerInformation(speaker: SpeakerInfo) { | |
Column( | |
modifier = Spacing(16.dp) | |
) { | |
Container(modifier = Height(180.dp) wraps Expanded) { | |
Clip(RoundedCornerShape(5.dp)) { | |
DrawImage(image = speaker.image) | |
} | |
} | |
Text(speaker.name) | |
Text(speaker.title) | |
Text(speaker.sessionTitle) | |
} | |
} |

State in Compose: Compose’un en รงok savunduฤu ลeylerden biri, data deฤiลikliklerinde extra birลey yapmadan direk view’in gรผncellenmesi. Data deฤiลtiฤinde bu fonksiyonlarฤฑn รงaฤrฤฑlฤฑฤ gรผncellenmiล bir UI yaratฤฑlmasฤฑ dฤฑลฤฑnda Compose aynฤฑ zamanda tek bir Composable’ฤฑn hangi dataya ihtiyacฤฑ olduฤuna da bakar ve sadece o componentleri recompose eder. Diฤerleri data deฤiลikliฤinden etkilenmemiล olurlar.
Managing State with @Model: Ekranda gรถrรผneni gรผncellemek iรงin Composable fonksiyonlarฤฑ farklฤฑ input parametreleriyle รงaฤฤฑrmak yerine, Compose bize @Model annotationฤฑnฤฑ รถneriyor. Compose fonksiyonunun input olarak aldฤฑฤฤฑ data @Model annotationฤฑnฤฑ kullanฤฑyorsa, data deฤiลtiฤinde otomatik olarak recompose olacak. @Model sayesinde Compose compiler’ฤฑ observable ve thread-safe bir ลekilde class’ฤฑ rewrite eder.
Aลaฤฤฑdaki kod รถrneฤindeki Counter widget’ฤฑnฤฑ kullandฤฑฤฤฑmฤฑz durumda, counter’ฤฑmฤฑz her tฤฑklayฤฑลda bir artacak ve bunun iรงin ekstra bir geliลtirme yapmadan ekranda sayฤฑnฤฑn deฤiลtiฤini gรถrebileceฤiz.
@Model | |
class CounterState(var count: Int = 0) | |
@Composable | |
fun Counter(state: CounterState) { | |
Button( | |
text = "I've been clicked ${state.count} times", | |
onClick = { | |
state.count++ | |
}, | |
style = ContainedButtonStyle(), | |
modifier = Spacing(24.dp) | |
) | |
} |

Flexible Layouts: Hem Row hem Column iรงin geรงerli olmak รผzere itemlarฤฑnฤฑ birbirini ardฤฑna yerleลtirirler. Bazฤฑ item’larฤฑn belli bir weight’le ekranฤฑ kaplamasฤฑnฤฑ istiyorsak Flexible modifier’ฤฑnฤฑ kullanabiliriz. (Inflexible default davranฤฑล) Flexible ilgili parametreyi match_parent yapฤฑp, weight’ini 1 verdiฤimiz case’de LinearLayout’da รงalฤฑลtฤฑฤฤฑ gibi รงalฤฑลฤฑr.
@Composable | |
fun StateSampleScreen( | |
names: List<String> = listOf("Android", "there"), | |
counterState: CounterState = CounterState() | |
) { | |
Column(modifier = ExpandedHeight) { | |
Column(modifier = Flexible(1f)) { | |
for (name in names) { | |
Greeting(name = name) | |
Divider(color = Color.Black) | |
} | |
} | |
Counter(counterState) | |
} | |
} |

Sฤฑrada Theming var. ลimdiye kadar konuลtuklarฤฑmฤฑz daha statik olarak deฤiลtirilen รถzelliklerdi. Peki biraz รถzelliลtirmek istersek bunu nasฤฑl yapacaฤฤฑz.
Theme de diฤer Composable Fonksiyonlar gibi Component hiyerarลisinin bir parรงasฤฑdฤฑr. Yukarฤฑdaki Container kullanฤฑm รถrneฤinde app’imize Material Theme’i vermiลtik. Bu da aslฤฑnda Material Theme altฤฑnda tanฤฑmlฤฑ olan deฤerleri kullanabileceฤimiz anlamฤฑna geliyor. Yine รถrnekte parametre olarak colors alฤฑyordu. Renkleri de รถzelleลtirebiliriz.
MaterialTheme, Material desing standartlarฤฑna gรถre styling principlerine tepki veren bir Composable fonksiyondur. ฤฐรงindeki tรผm componentlere bu styling information geรงer ve kullanฤฑlabilir.
@Composable | |
fun Title(title: String) { | |
Text(title, | |
style = themeTypography.h6) | |
} |
Tamam son olarak da listelerden bahsedelim. Listeler olmadan bir app yazmak รงok da mรผmkรผn olmayabilir sanฤฑrฤฑm. Bildiฤiniz รผzere eskiden ListView’ler vardฤฑ ve biraz da ui performasฤฑnฤฑn iyi/kรถtรผ olmasฤฑnฤฑn developer’ฤฑn elindeydi. Sonrasฤฑnda bu problemi ortadan kaldฤฑran RecyclerView’le tanฤฑลtฤฑk. Compose’da ise bunu scrollinglist yapฤฑyor. Kullanฤฑmฤฑ video izlediฤim kadarฤฑyla รงok daha simple. Ancak ลรถyle bir sorun vardฤฑ, benim denediฤim dev-03’te henรผz bulunmuyordu. Yeni versiyonlarla tabi gelmiล olabilir. Jetnews รถrnek app’ini inceliฤimde ลimdilik bu fonksiyonelitiyi verticalscroller’la รงรถzdรผklerini gรถrdรผm.
@Composable | |
fun SpeakerList(speakers: List<SpeakerInfo>){ | |
ScrollingList(speakers) { speaker -> | |
SpeakerInformation(speaker) | |
} | |
} |
Compose’un genel bakฤฑล aรงฤฑsฤฑ ve temel componentlerin kullanฤฑmฤฑyla ilgili umarฤฑm fikir vermesi aรงฤฑsฤฑndan faydalฤฑ olmuลtur. Genel olarak toparlayacak olursak, Compose biraz ui kararlarฤฑnฤฑ developer’ฤฑn elinden alฤฑp, basitleลtirip, daha az kod yazฤฑlmasฤฑnฤฑ saฤlฤฑyor. Bunlar sรผreci basitleลtirirken komplex layoutlarda ne kadar baลarฤฑlฤฑ olabileceฤi de soru iลareti doฤuruyor. ลu an hala รงok yeni, developer preview’ฤฑnda, geliลimini yolda incelemek biz Android geliลtiriciler faydalฤฑ olacaktฤฑr.
Kod รถrnekleri iรงin linkteki sample projeyi inceleyebilirsiniz. ๐
References:
- https://www.youtube.com/watch?v=VsStyq4Lzxo
- JetpackCompose Basics
https://codelabs.developers.google.com/codelabs/jetpack-compose-basics/ - Understanding Compose (Android Dev Summit ’19)
https://www.youtube.com/watch?v=Q9MtlmmN4Q0 - What’s New in Jetpack Compose (Android Dev Summit ’19
3 responses to “Building UI with Compose”
baลarฤฑlฤฑ harika teknoloji haberleriyle dolu gรผzel bir blog olmuล aslฤฑnda teknoloji hakkฤฑnda birลey alฤฑnฤฑrken size danฤฑลฤฑlmalฤฑ
[…] ← Previous […]
[…] To read the article in Turkish you can use the link1 or link2. […]