Skip to content

Instantly share code, notes, and snippets.

@ulaserdegor
Last active October 19, 2022 11:04
Show Gist options
  • Save ulaserdegor/777b9452a2f39a83ca39ee1d3b8f16d8 to your computer and use it in GitHub Desktop.
Save ulaserdegor/777b9452a2f39a83ca39ee1d3b8f16d8 to your computer and use it in GitHub Desktop.
@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