Android Jetpack Compose – Bottom Sheet Kullanımı

Klasik Android’de Bottom Sheet Dialog nesnesine karşılık gelen Jetpack Compose öğelerinden olan ve aynı zamanda bir Scaffold yapısı olan Bottom Sheet yapısının kullanımına değinelim. Yapacağımız çalışmada ekranın en alt kısmından belirtilen boyutta bir sayfa açtırarak üstte gözükecek olan sayfadan da işlem gerçekleştirebileceğiz. Estetik ve fonksiyonel bir kullanım içeren Bottom Sheet yapısının şimdi nasıl kullanılabileceğine ilişkin örneğine değinelim;

Çıktı:

Örneğimizde bir butona tıklandığında Bottom Sheet penceresini açtırıp, bu açılan pencere üzerinde de bir işlem gerçekleştirme ve açılan dialogu kapatma eyleminin nasıl gerçekleştirileceğini görelim;

Surface scope’u içerisine gerekli olan state, liste ve değişkenlerimizi üretelim;

val creditCards = listOf(
                    "1234 5678 9012 3456 - YAPI KREDİ",
                    "5400 0001 1002 0034 - GARANTİ",
                    "6000 0001 1002 0034 - VAKIFBANK (MAAŞ)"
)

Üreteceğim radio group içerisinde göstermek istediğim radio button nesnelerinin yazılarının tanımlanabilmesi için liste ürettim.

val (selectedOpt, onOptionSelected) = remember{ mutableStateOf(creditCards[1])}

Seçilen radio button nesnesinin seçili halde bulunabilmesi için hafızada remember ile state’ini kaydettim. Varsayılanda 2. elemanı seçili göstermesini istedim.

val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(bottomSheetState =
                BottomSheetState(BottomSheetValue.Collapsed))

Aşağı kısımlarda BottomSheet nesnesi üreteceğiz, bu bottom sheet’in açılı olma veya kapalı olma durumunu barındıran bir state ürettik.

val coroutineScope = rememberCoroutineScope()

coroutine kullanabilmek adına coroutineScope adında bir değişken üretiyorum.

Şimdi bottomSheetDialog adında fonksiyon üretelim ve gerekli olan argümanları tanımlayalım;

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun bottomSheetDialog(
bottomSheetScaffoldState:BottomSheetScaffoldState,
creditCards:List<String>,
applicationContext:Context,
coroutineScope:CoroutineScope
){
 // kodlar bu aralığa yazılacak.
}

bu fonksiyonun en üst satırına, yukarıda oluşturduğumuz aşağıda belirttiğim satırı kesip taşıyalım;

val (selectedOpt, onOptionSelected) = remember{ mutableStateOf(creditCards[1])}

foksiyonun şuanki hali;

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun bottomSheetDialog(
bottomSheetScaffoldState:BottomSheetScaffoldState,
creditCards:List<String>,
applicationContext:Context,
coroutineScope:CoroutineScope
){
   val (selectedOpt, onOptionSelected) = remember{ mutableStateOf(creditCards[1])}
}

şimdi bu kesip yapıştırdığımız satırın hemen altına, BottomSheetScaffold adlı bir Scaffold üreteceğiz.

BottomSheetScaffold(
        scaffoldState = bottomSheetScaffoldState,
        sheetContent =  {
// bundan sonra yazacağımız kodlarımız bu aralıkta olacaktır.
        },
        sheetPeekHeight = 5.dp
(){}

buradaki scaffoldState, bottomSheet’in açık olup olmadığı durumunu tutuyor. sheetPeekHeight sayfanın en alt kısmından parmağımız ile yukarı doğru sürüklediğimizde de sheet’in açılabilmesini sağlayabilmemiz için gerekmektedir. Eğer bu özelliği kapatmak istiyorsanız height değeri olarak 0.dp değerini verebilirsiniz. sheetContent ise açılan dialog sayfası içerisinde göstermek istediğimiz componentleri tanımladığımız alanı ifade etmektedir.

Şimdi sırasıyla sheetContent içerisine gerekli olan nesnelerimizi tanımlayalım.

Box(
                Modifier
                    .fillMaxWidth()
                    .height(240.dp)
                    .background(Color(0xFFE6E6E6))
            ) {
                // aşağıda yazacağımız kodlar bu aralığa eklenmelidir.
}

burada bir kutu ürettik ve bu kutu; bottom sheet dialogumuzun yüksekliğini, arkaplan rengini ve genişliğini tanımlayabildiğimiz ana kapsayıcımız olacaktır.

Bu Box nesnemizin içerisine kullanıcının örneğin bir ödeme gerçekleştirmesi durumunda kayıtlı kart bilgilerini seçebileceği ve ne kadar ödeyeceğini tanımlayabilecek yazıların ve butonların eklenmesini sağlayalım. Şimdi gerekli olan yazılarımızı tanımlayalım;

Column(Modifier.fillMaxSize(), verticalArrangement = Arrangement.Top) {
                    Text(
                        text = "Amount: 45$",
                        modifier = Modifier.align(Alignment.CenterHorizontally),
                        fontSize = 20.sp,
                        color = Color.Black
                    )

                    Text(
                        text = "Choose Credit Card:",
                        modifier = Modifier.align(Alignment.CenterHorizontally),
                        fontSize = 20.sp,
                        color = Color.Black
                    )
}

Burada Column ürettik ve içerisine iki adet Text ürettik bu Textler alt satırlar halde gözükecektir.

hemen altına ise tekrar bir Column üretelim ve bu Column içerisinde kullanıcının kayıtlı kredi kart numaraları listelensin.

Column(modifier = Modifier.padding(0.dp,70.dp,0.dp,0.dp)){
                    creditCards.forEach{ text ->
                        Row(modifier = Modifier
                            .fillMaxWidth()
                            .padding(5.dp)
                            .selectable(
                                selected = (text == selectedOpt),
                                onClick = { onOptionSelected(text) }
                            )) {
                            RadioButton(
                                selected = (text == selectedOpt),
                                modifier = Modifier.height(25.dp),
                                onClick = {
                                    onOptionSelected(text)
                                    Toast.makeText(applicationContext,text,Toast.LENGTH_LONG).show()
                                }
                            )
                            Text(
                                text = text,
                                modifier = Modifier.height(25.dp)
                            )
                        }
                    }
}

Her Row içerisinde RadioButton ve hemen yanında Text ekledik. Buradaki Text radio button nesnemizde göstermek istediğimiz yazıyı belirttiğimiz alanı ifade etmektedir. Row’a selectable özelliği ekleyerek, RadioButton’a da tıklansa, yazıya da tıklansa ilgili liste elemanını seçmiş oluyoruz.

Box scope’unu kapattıktan sonra, hemen bir alt satıra yine bir Row ekleyip, solda İptal, sağda ise Öde adlı butonlarımızın bulunacağı tasarımı şekillendirip, butonlara tıklandığında sheet’in gizlenmesini sağlıyoruz;

Row() {
                Button(onClick = {
                    coroutineScope.launch {
                        bottomSheetScaffoldState.bottomSheetState.collapse()
                    }
                },modifier = Modifier.fillMaxWidth().height(50.dp).weight(0.5f).padding(5.dp)) {
                    Text(text = "Cancel")
                }
                Button(onClick = {
                    coroutineScope.launch {
                        bottomSheetScaffoldState.bottomSheetState.collapse()
                    }
                    Toast.makeText(applicationContext,selectedOpt+"\n Hesabından ödeme çekildi!",Toast.LENGTH_LONG).show()
                },modifier = Modifier.fillMaxWidth().height(50.dp).weight(0.5f).padding(5.dp)) {
                    Text(text = "Pay Now")
                }
}

onCreate metodumuza tekrar dönüp, ekrana bir buton ekleyip sheet’in açılması, tekrar tıklandığında ise kapanmasını sağlayalım. Bu arada onCreate bulunan setContent’deki son kodlarımız şöyle olacaktır;

setContent {
            Surface(
                modifier = Modifier.fillMaxSize(),
                color = MaterialTheme.colors.background
            ) {

                val creditCards = listOf(
                    "1234 5678 9012 3456 - YAPI KREDİ",
                    "5400 0001 1002 0034 - GARANTİ",
                    "6000 0001 1002 0034 - VAKIFBANK (MAAŞ)"
                )


                val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(bottomSheetState =
                BottomSheetState(BottomSheetValue.Collapsed))

                val coroutineScope = rememberCoroutineScope()




                Column(
                    Modifier.fillMaxSize(),
                    verticalArrangement = Arrangement.Center,
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    Button(onClick = {
                        coroutineScope.launch {
                            if (bottomSheetScaffoldState.bottomSheetState.isCollapsed){
                                bottomSheetScaffoldState.bottomSheetState.expand()
                            }else{
                                bottomSheetScaffoldState.bottomSheetState.collapse()
                            }
                        }
                    },
                        modifier = Modifier,
                        colors = ButtonDefaults.buttonColors(backgroundColor = Color(0xFF0F9D98))) {
                        Text(text = "Click to Pay", color = Color.White)
                    }
                }

            }
}

bottomSheetDialog fonksiyonumuzun son hali ise;


@OptIn(ExperimentalMaterialApi::class)
@Composable
fun bottomSheetDialog(bottomSheetScaffoldState: BottomSheetScaffoldState,creditCards:List<String>,applicationContext:Context,coroutineScope:CoroutineScope){
    val (selectedOpt, onOptionSelected) = remember{ mutableStateOf(creditCards[1])}
    BottomSheetScaffold(
        scaffoldState = bottomSheetScaffoldState,
        sheetContent =  {
            Box(
                Modifier
                    .fillMaxWidth()
                    .height(240.dp)
                    .background(Color(0xFFE6E6E6))
            ) {
                Column(Modifier.fillMaxSize(), verticalArrangement = Arrangement.Top) {
                    Text(
                        text = "Amount: 45$",
                        modifier = Modifier.align(Alignment.CenterHorizontally),
                        fontSize = 20.sp,
                        color = Color.Black
                    )

                    Text(
                        text = "Choose Credit Card:",
                        modifier = Modifier.align(Alignment.CenterHorizontally),
                        fontSize = 20.sp,
                        color = Color.Black
                    )
                }

                Column(modifier = Modifier.padding(0.dp,70.dp,0.dp,0.dp)){
                    creditCards.forEach{ text ->
                        Row(modifier = Modifier
                            .fillMaxWidth()
                            .padding(5.dp)
                            .selectable(
                                selected = (text == selectedOpt),
                                onClick = { onOptionSelected(text) }
                            )) {
                            RadioButton(
                                selected = (text == selectedOpt),
                                modifier = Modifier.height(25.dp),
                                onClick = {
                                    onOptionSelected(text)
                                    Toast.makeText(applicationContext,text,Toast.LENGTH_LONG).show()
                                }
                            )
                            Text(
                                text = text,
                                modifier = Modifier.height(25.dp)
                            )
                        }
                    }
                }

            }
            Row() {
                Button(onClick = {
                    coroutineScope.launch {
                        bottomSheetScaffoldState.bottomSheetState.collapse()
                    }
                },modifier = Modifier.fillMaxWidth().height(50.dp).weight(0.5f).padding(5.dp)) {
                    Text(text = "Cancel")
                }
                Button(onClick = {
                    coroutineScope.launch {
                        bottomSheetScaffoldState.bottomSheetState.collapse()
                    }
                    Toast.makeText(applicationContext,selectedOpt+"\n Hesabından ödeme çekildi!",Toast.LENGTH_LONG).show()
                },modifier = Modifier.fillMaxWidth().height(50.dp).weight(0.5f).padding(5.dp)) {
                    Text(text = "Pay Now")
                }
            }
        },
        sheetPeekHeight = 5.dp
    ){}
}

Keyifli çalışmalar dilerim.

Yorum bırakın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Scroll to Top