-
-
Save ulaserdegor/777b9452a2f39a83ca39ee1d3b8f16d8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@file:OptIn(ExperimentalPagerApi::class) | |
package com.ulaserdegor.jc.sample | |
import androidx.compose.foundation.Image | |
import androidx.compose.foundation.background | |
import androidx.compose.foundation.border | |
import androidx.compose.foundation.layout.Arrangement | |
import androidx.compose.foundation.layout.Box | |
import androidx.compose.foundation.layout.Column | |
import androidx.compose.foundation.layout.PaddingValues | |
import androidx.compose.foundation.layout.fillMaxSize | |
import androidx.compose.foundation.layout.fillMaxWidth | |
import androidx.compose.foundation.layout.padding | |
import androidx.compose.foundation.layout.size | |
import androidx.compose.foundation.rememberScrollState | |
import androidx.compose.foundation.shape.RoundedCornerShape | |
import androidx.compose.foundation.verticalScroll | |
import androidx.compose.material.Text | |
import androidx.compose.material.TopAppBar | |
import androidx.compose.runtime.Composable | |
import androidx.compose.ui.Alignment | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.draw.alpha | |
import androidx.compose.ui.draw.clip | |
import androidx.compose.ui.graphics.Color | |
import androidx.compose.ui.graphics.ColorFilter | |
import androidx.compose.ui.graphics.graphicsLayer | |
import androidx.compose.ui.layout.ContentScale | |
import androidx.compose.ui.platform.LocalConfiguration | |
import androidx.compose.ui.platform.LocalContext | |
import androidx.compose.ui.res.painterResource | |
import androidx.compose.ui.text.TextStyle | |
import androidx.compose.ui.text.font.FontWeight | |
import androidx.compose.ui.text.style.TextAlign | |
import androidx.compose.ui.unit.dp | |
import androidx.compose.ui.unit.sp | |
import androidx.compose.ui.util.lerp | |
import coil.compose.AsyncImagePainter | |
import coil.request.ImageRequest | |
import coil.size.Size | |
import com.google.accompanist.pager.ExperimentalPagerApi | |
import com.google.accompanist.pager.HorizontalPager | |
import com.google.accompanist.pager.calculateCurrentOffsetForPage | |
import com.google.accompanist.pager.rememberPagerState | |
import kotlin.math.absoluteValue | |
@Composable | |
fun SampleScreen( | |
) { | |
val title = "Title Compose" | |
val slideUrls = arrayListOf( | |
"https://i.imgur.com/YY6E6Dn.png", | |
"https://i.imgur.com/u4qJaoc.png", | |
"https://i.imgur.com/DP9sgX1.png" | |
) | |
val scrollState = rememberScrollState() //ekran scroll'unu dinliyoruz. bu değere göre TopAppBar' ın alpha 'sı güncellenecek. | |
Box( | |
modifier = Modifier | |
.background(Color.White) | |
.fillMaxSize() | |
) { | |
Column( | |
modifier = Modifier | |
.fillMaxSize() | |
) { | |
TopAppBar( | |
backgroundColor = Color.Black.copy( | |
alpha = | |
kotlin.math.max( | |
0.0f, | |
scrollState.value / (scrollState.value + 14f) //scroll' a göre appbar'ın alpha' sı güncellendi. | |
) | |
), | |
contentColor = Color.White, | |
elevation = 0.dp //default appbar' ın kendi elevation' unu kapatıyoruz | |
) { | |
Box(modifier = Modifier.fillMaxWidth()) { | |
Text( | |
textAlign = TextAlign.Center, | |
text = title, | |
modifier = Modifier | |
.align(Alignment.Center) | |
.alpha( | |
kotlin.math.max( | |
0.0f, | |
scrollState.value / (scrollState.value + 14f) | |
) | |
), | |
style = TextStyle(fontWeight = FontWeight.Bold) | |
) | |
} | |
} | |
Column( | |
horizontalAlignment = Alignment.CenterHorizontally, | |
verticalArrangement = Arrangement.spacedBy(16.dp), // column içerisinde ki item' lerin dikey de aralarında olması istenen padding verildi. | |
modifier = Modifier | |
.fillMaxSize() | |
.verticalScroll(scrollState) | |
.padding(bottom = 16.dp) | |
) { | |
Text( | |
text = title, | |
style = TextStyle(fontSize = 24.sp) | |
) | |
Text( | |
text = "Bulunduğumuz ekranı, diğer ekranlar üzerinde devam etmesini sağlayan bir yapıdır.\nBunu bir örnek üzerinden açıklayalım. Bir video oynayan ekrana sahip olduğumuzu düşünelim ve video’yu başlatıp izlerken, bir taraftanda ister uygulama içerisinde ister uygulamadan çıkıp cihaz içerisinde dolaşmak istediğimizde ve video’nun durmadan, kapanmadan devam etmesini istediğimiz durumda Picture in Picture modu yardımımıza koşuyor.", | |
modifier = Modifier.padding(horizontal = 16.dp) | |
) | |
Text( | |
text = "Kullanıcı etkileşimlerini test etmek, kullanıcıların uygulamanızla etkileşim kurarken beklenmedik sonuçlarla karşılaşmamasını veya kötü bir deneyim yaşamamasını sağlamaya yardımcı olur.\nUygulamanızın kullanıcı arabiriminin doğru çalıştığını doğrulamanız gerekiyorsa, kullanıcı arabirimi (UI) testleri oluşturma alışkanlığı edinmelisiniz.", | |
modifier = Modifier.padding(horizontal = 16.dp) | |
) | |
CustomSlider(slideUrls) | |
Text( | |
text = "Uygulama içerisinde farklı birçok ekrana sahipseniz ve uygulamanın ekranlar arasındaki dolaşımı esnasında, bir ekrandan başka bir ekrana geçişlerin kusursuz olması açısından nested navigation tam olarak ihtiyacımız olan şey.", | |
modifier = Modifier.padding(horizontal = 16.dp) | |
) | |
} | |
} | |
} | |
} | |
@Composable | |
fun CustomSlider(sliders: List<String>?) { | |
val configuration = LocalConfiguration.current | |
val itemPadding = configuration.screenWidthDp.dp * .18f | |
val pagerState = rememberPagerState( | |
initialPage = 0, | |
) | |
Column { | |
HorizontalPager( | |
contentPadding = PaddingValues(horizontal = itemPadding), | |
count = sliders?.size ?: 1, | |
state = pagerState, | |
itemSpacing = 0.dp, | |
modifier = Modifier | |
.fillMaxSize() | |
) { page -> | |
Box( | |
modifier = Modifier | |
.graphicsLayer { //slider item' lerinin animsayonu atanıyor. | |
val pageOffset = calculateCurrentOffsetForPage(page).absoluteValue | |
lerp( | |
start = 0.8f, | |
stop = 1f, | |
fraction = 1f - pageOffset.coerceIn(.0f, 1f) | |
).also { scale -> | |
scaleX = scale | |
scaleY = scale | |
} | |
alpha = lerp( | |
start = 0.4f, | |
stop = 1f, | |
fraction = 1f - pageOffset.coerceIn(0f, 1f) | |
) | |
} | |
.fillMaxSize() | |
) { | |
val asyncPainter = rememberAsyncImagePainterWithGif( //resimler yüklenene kadar gösterilecek placeholder için yazılan extension kullanıldı. | |
model = ImageRequest.Builder(LocalContext.current) | |
.data(data = sliders?.get(page)) | |
.size(Size.ORIGINAL) //gelen resim size' ı verildi. | |
.build() | |
) | |
when (asyncPainter.state) { | |
is AsyncImagePainter.State.Loading, | |
is AsyncImagePainter.State.Error, | |
is AsyncImagePainter.State.Empty, | |
-> { | |
Image( | |
painter = painterResource(R.drawable.place_holder_image), | |
contentDescription = "", | |
colorFilter = ColorFilter.tint(Color.White.copy(alpha = .25f)), | |
modifier = Modifier | |
.size(64.dp) | |
.align(Alignment.Center) | |
) | |
} | |
else -> Unit | |
} | |
Image( | |
painter = asyncPainter, | |
contentDescription = null, | |
contentScale = ContentScale.FillWidth, | |
modifier = Modifier | |
.clip(RoundedCornerShape(8.dp)) | |
.border(width = 1.dp, color = Color.LightGray, shape = RoundedCornerShape(8.dp)) | |
.fillMaxSize() | |
) | |
} | |
} | |
} | |
} | |
@Composable | |
fun rememberAsyncImagePainterWithGiff(model: Any?): AsyncImagePainter { | |
val context = LocalContext.current | |
val imageLoader = ImageLoader.Builder(context) | |
.components { | |
if (Build.VERSION.SDK_INT >= 28) { | |
add(ImageDecoderDecoder.Factory()) | |
} else { | |
add(GifDecoder.Factory()) | |
} | |
} | |
.build() | |
return rememberAsyncImagePainter( | |
imageLoader = imageLoader, | |
model = model, | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment