Teknolojinin hızlı bir şekilde gelişimiyle yazılımcıların proje tasarımını oluşturma süreçlerini kolaylaştırmak ve hızlandırmak için birçok yapı ortaya çıktı.
“Jetpack Compose ile Adım Adım Tasarım” adlı makalem de Jetpack Compose ve avantajlarının neler olduğunu ve listeleme ekranı yapmayı aşama aşama örnekleyerek açıklamıştım.
Bu makalemde ise Android UI‘yı Jetpack Compose kullanarak Tabs sekmelerini nasıl oluşturulacağını ve Accompanist ile sekmeler arasında nasıl gezineceğimizi örnekleyeceğim.
Yapacağımız örneğimizin çıktısı:
1-Compose Proje Oluşturma
Compose kullanabilmek için ilk önce Android Studio Arctic Fox sürümünü indirmeniz gerekir. Android Studio’da File > New yolunu takip edip New Project ekranında Empty Compose Activity arayüz taslağını seçmelisiniz. Next yapıp projenizi oluşturun.
2-Projede Gerekli Bazı Ayarlar
Projenizin ana dizinindeki build.gradle dosyasını açmalısınız. dependencies blogları arasına aşağıdaki kodu ekleyerek Accompanist kütüphanesini yükleyelim.
1 2 |
implementation "com.google.accompanist:accompanist-pager:0.19.0" implementation "com.google.accompanist:accompanist-pager-indicators:0.19.0" |
3- Tabs Ekranlarını Oluşturma
Sekmeleri (Tabs) oluşturmaya başlamadan önce, bir sekme seçtiğimizde görüntüleyeceğimiz ekranları oluşturmamız gerekir. Bunun için paket ismine sağ tıklayıp New->Kotlin Class/File alanını seçin. Açılan pencerede File seçip, sınıf ismini ContentScreens yazdıktan sonra enter basıp dosyayı oluşturun.
Her bir tab ekranı için MusicScreen, MoviesScreen ve BooksScreen adında Composable fonksiyonlar oluşturdum. Bu fonksiyonların içinde oluşturacağım arayüz tasarımını görüntülemek için her biri için @Preview Composable yapıları oluşturdum ve ilgili fonksiyonları içlerinde çağırdım. Fonksiyonlar içinde yazdığım arayüz Compose oluşumunu ve açıklamalarını inceleyelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.* import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.colorResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.sp @Composable fun MusicScreen() { //Column ile dikeyde alan oluşturup, arkaplan rengive içinde //bulanacak olan Text elementini hızaladım Column( modifier = Modifier .fillMaxSize() .background(colorResource(id = R.color.white)) .wrapContentSize(Alignment.Center) ) { //Yazı alanı oluşturup boyut, renk, font tipi vb özelliklerini atadım Text( text = "Music View", fontWeight = FontWeight.Bold, color = Color.Black, modifier = Modifier.align(Alignment.CenterHorizontally), textAlign = TextAlign.Center, fontSize = 25.sp ) } } @Preview(showBackground = true) @Composable fun MusicScreenPreview() { MusicScreen() } @Composable fun MoviesScreen() { Column( modifier = Modifier .fillMaxSize() .background(colorResource(id = R.color.white)) .wrapContentSize(Alignment.Center) ) { Text( text = "Movies View", fontWeight = FontWeight.Bold, color = Color.Black, modifier = Modifier.align(Alignment.CenterHorizontally), textAlign = TextAlign.Center, fontSize = 25.sp ) } } @Preview(showBackground = true) @Composable fun MoviesScreenPreview() { MoviesScreen() } @Composable fun BooksScreen() { Column( modifier = Modifier .fillMaxSize() .background(colorResource(id = R.color.white)) .wrapContentSize(Alignment.Center) ) { Text( text = "Books View", fontWeight = FontWeight.Bold, color = Color.Black, modifier = Modifier.align(Alignment.CenterHorizontally), textAlign = TextAlign.Center, fontSize = 25.sp ) } } @Preview(showBackground = true) @Composable fun BooksScreenPreview() { BooksScreen() } |
4- Tab Items Oluşturma
Her sekme öğesinde (Tab items) başlık ve iconları gösterebilmek için kotlin dosyası oluşturacağız. Bunun için paket ismine sağ tıklayıp New->Kotlin Class/File alanını seçin. Açılan pencerede Sealed Class seçip, sınıf ismini TabItem yazdıktan sonra enter basıp dosyayı oluşturun.
Tab’larda kullanacağım iconları res->drawable dosyasına sağ tıklayıp Vector Asset sayfasından oluşturdum. Bu iconlara github linkinde bulunan proje dosyasından erişebilirsiniz. Kodlarımızı açıklamalarıyla inceleyelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import androidx.compose.runtime.Composable typealias ComposableFun = @Composable () -> Unit sealed class TabItem(var icon: Int, var title: String, var screen: ComposableFun) { //Parametrede icon ve tab ismini tanımladık object Music : TabItem(R.drawable.ic_music, "Music", { //Music sekmesine tıklandığında hangi compose fonksiyonundaki ekran göstereleceğini belirtiyoruz MusicScreen() }) object Movies : TabItem(R.drawable.ic_movie, "Movies", { //Movies sekmesine tıklandığında hangi compose fonksiyonundaki ekran göstereleceğini belirtiyoruz MoviesScreen() }) object Books : TabItem(R.drawable.ic_book, "Books", { BooksScreen() }) } |
5-Tab Item ve Tab Ekranlarını Birleştirme
Bir önceki aşamalarda oluşturduğumuz Tab Item ve Tab ekranlarını birbirleriyle ilişkilendirerek Tab item’lara tıkladığımızda yada ekran kaydırma yapıldığında tab’lar arasında geçişi sağlayacağız. Bu işlemi MainActivity sınıfında yapılmasını sağladım. Tüm kodları açıklamalarıyla inceleyebilirsiniz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.Column import androidx.compose.material.* import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.sp import com.google.accompanist.pager.* import kotlinx.coroutines.launch class MainActivity : ComponentActivity() { @ExperimentalMaterialApi @ExperimentalPagerApi override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MainScreen() } } } //Ana ekranda yapılacaklar için MainScreen fonksiyonu oluşturalım @ExperimentalMaterialApi @ExperimentalPagerApi @Composable fun MainScreen() { //TabItem dosyasında belirlediğim tab öğelerini diziye yerleşitiriyoruz val tabs = listOf(TabItem.Music, TabItem.Movies, TabItem.Books) val pagerState = rememberPagerState() //Scaffold yerleşim yapısına TopBarfonksiyonunu çağırarak topbar ekleyelim. Scaffold( topBar = { TopBar() }, ) { Column { //Tabs fonksiyonunu çağırarak tab ları görünür yaptım. Tabs(tabs = tabs, pagerState = pagerState) //TabsContent fonksiyonunu çağırarak ilgili ekran içeriklerini gösterdim TabsContent(tabs = tabs, pagerState = pagerState) } } } //MainScreen fonksiyonunu çağırarak yapılan arayüz kodlarımızı //önizleme yapıyoruz @ExperimentalMaterialApi @ExperimentalPagerApi @Preview(showBackground = true) @Composable fun MainScreenPreview() { MainScreen() } //Bar bölümündeki başlığı, rengini ve font boyutunu tanımlıyoruz @Composable fun TopBar() { TopAppBar( title = { Text("Tabs Jetpack Compose", fontSize = 18.sp) }, contentColor = Color.White ) } //TopBar fonksiyonunda yapılan arayüz kodlarımızı //önizleme yapıyoruz @Preview(showBackground = true) @Composable fun TopBarPreview() { TopBar() } @ExperimentalMaterialApi @ExperimentalPagerApi @Composable fun Tabs(tabs: List<TabItem>, pagerState: PagerState) { val scope = rememberCoroutineScope() TabRow( selectedTabIndex = pagerState.currentPage, //Tab başlıklarının rengini belirliyoruz contentColor = Color.White, indicator = { tabPositions -> TabRowDefaults.Indicator( Modifier.pagerTabIndicatorOffset(pagerState, tabPositions) ) }) { //tabs dizisinden gelen icon, başlık bilgilerinin Tabs görünümüne aktarılması tabs.forEachIndexed { index, tab -> LeadingIconTab( icon = { Icon(painter = painterResource(id = tab.icon), contentDescription = "") }, text = { Text(tab.title) }, selected = pagerState.currentPage == index, //Tab öğelerine tıklandığında ilgili tab ekranının gösterilmesi onClick = { scope.launch { pagerState.animateScrollToPage(index) } }, ) } } } @ExperimentalPagerApi @ExperimentalMaterialApi @Preview(showBackground = true) @Composable fun TabsPreview() { val tabs = listOf( TabItem.Music, TabItem.Movies, TabItem.Books ) val pagerState = rememberPagerState() Tabs(tabs = tabs, pagerState = pagerState) } //Seçilen Tab öğesinin ilgili ekranındaki içeriği gösteren fonksiyon @ExperimentalPagerApi @Composable fun TabsContent(tabs: List<TabItem>, pagerState: PagerState) { HorizontalPager(state = pagerState, count = tabs.size) { page -> tabs[page].screen() } } //TabsContent fonksiyonunu önizleme @ExperimentalPagerApi @Preview(showBackground = true) @Composable fun TabsContentPreview() { val tabs = listOf( TabItem.Music, TabItem.Movies, TabItem.Books ) val pagerState = rememberPagerState() TabsContent(tabs = tabs, pagerState = pagerState) } |
Proje kodlarına github linkinden ulaşabilirsiniz.
Kaynak
johncodeos.com/how-to-create-tabs-with-jetpack-compose