diff --git a/app/.gitignore b/app/.gitignore index 42afabf..3f8400c 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -1 +1,2 @@ -/build \ No newline at end of file +/build +src/main/assets \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 39c7632..7a1628b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -51,29 +51,30 @@ android { } dependencies { - - implementation("androidx.core:core-ktx:1.12.0") - implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") - implementation("androidx.activity:activity-compose:1.8.2") - implementation(platform("androidx.compose:compose-bom:2023.08.00")) + val lifecycleVersion = "2.8.2" implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.material3:material3") + implementation("androidx.constraintlayout:constraintlayout-compose:1.0.1") + // ViewModel + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycleVersion") + // LiveData + implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycleVersion") + // Lifecycle utilities for Compose + implementation("androidx.lifecycle:lifecycle-runtime-compose:$lifecycleVersion") + implementation("androidx.compose.runtime:runtime-livedata:1.6.8") + + implementation("androidx.core:core-ktx:1.13.1") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion") + implementation("androidx.activity:activity-compose:1.9.0") + implementation(platform("androidx.compose:compose-bom:2024.06.00")) + testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") - androidTestImplementation(platform("androidx.compose:compose-bom:2023.08.00")) + androidTestImplementation(platform("androidx.compose:compose-bom:2024.06.00")) androidTestImplementation("androidx.compose.ui:ui-test-junit4") debugImplementation("androidx.compose.ui:ui-tooling") debugImplementation("androidx.compose.ui:ui-test-manifest") - - val lifecycle_version = "2.6.2" - // ViewModel - implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version") - // LiveData - implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version") - // Lifecycle utilities for Compose - implementation("androidx.lifecycle:lifecycle-runtime-compose:$lifecycle_version") - implementation("androidx.compose.runtime:runtime-livedata:1.5.4") } \ No newline at end of file diff --git a/app/src/main/assets/pager.png b/app/src/main/assets/pager.png new file mode 100644 index 0000000..bff0d9e Binary files /dev/null and b/app/src/main/assets/pager.png differ diff --git a/app/src/main/java/com/demo/composeapplication/MainActivity.kt b/app/src/main/java/com/demo/composeapplication/MainActivity.kt index ae407e4..af47871 100644 --- a/app/src/main/java/com/demo/composeapplication/MainActivity.kt +++ b/app/src/main/java/com/demo/composeapplication/MainActivity.kt @@ -110,8 +110,7 @@ class MainActivity : ComponentActivity() { ) { //Greeting("Compose") //Counter() - //MainUI() - HorizontalList() + MainUI() } } } diff --git a/app/src/main/java/com/demo/composeapplication/ui/screens/CommonElementsInCompose.kt b/app/src/main/java/com/demo/composeapplication/ui/screens/CommonElementsInCompose.kt index f4983b1..5f11a94 100644 --- a/app/src/main/java/com/demo/composeapplication/ui/screens/CommonElementsInCompose.kt +++ b/app/src/main/java/com/demo/composeapplication/ui/screens/CommonElementsInCompose.kt @@ -1,11 +1,6 @@ package com.demo.composeapplication.ui.screens -import android.provider.CalendarContract.Colors -import android.text.Spannable -import android.text.style.BackgroundColorSpan import androidx.compose.foundation.background -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.interaction.collectIsPressedAsState import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth @@ -13,7 +8,6 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.CutCornerShape import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.ClickableText import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.AccountBox import androidx.compose.material3.AssistChip @@ -22,34 +16,25 @@ import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.ElevatedButton import androidx.compose.material3.ElevatedCard -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.FilledTonalButton import androidx.compose.material3.FilterChip import androidx.compose.material3.Icon import androidx.compose.material3.InputChip import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedCard -import androidx.compose.material3.ShapeDefaults import androidx.compose.material3.SuggestionChip import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.drawscope.DrawStyle -import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.core.text.buildSpannedString -import androidx.core.text.toSpannable -@OptIn(ExperimentalMaterial3Api::class) @Composable fun DisplayCommonContents() { Column(modifier = Modifier.background(Color.LightGray)) { diff --git a/app/src/main/java/com/demo/composeapplication/ui/screens/ConstraintDemo.kt b/app/src/main/java/com/demo/composeapplication/ui/screens/ConstraintDemo.kt new file mode 100644 index 0000000..aa14bf0 --- /dev/null +++ b/app/src/main/java/com/demo/composeapplication/ui/screens/ConstraintDemo.kt @@ -0,0 +1,76 @@ +package com.demo.composeapplication.ui.screens + +import android.content.res.Configuration +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.layoutId +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import androidx.constraintlayout.compose.ChainStyle +import androidx.constraintlayout.compose.ConstraintLayout +import androidx.constraintlayout.compose.ConstraintSet + +@Composable +fun ComposeDemo() { + val margin = if(LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE) 32.dp else 16.dp + ConstraintLayout(getConstraintSet(margin)) { + + Text(text = "First View", modifier = Modifier.layoutId("text1")) + Text(text = "Second View", modifier = Modifier.layoutId("text2")) + Text(text = "Third View", modifier = Modifier.layoutId("text3")) + Text(text = "Fourth View", modifier = Modifier.layoutId("text4")) + } +} + + +fun getConstraintSet(margin: Dp): ConstraintSet { + return ConstraintSet { + val text1Ref = createRefFor("text1") + val text2Ref = createRefFor("text2") + val text3Ref = createRefFor("text3") + val text4Ref = createRefFor("text4") + + val guidelineStart = createGuidelineFromStart(8.dp) + val guidelineEnd = createGuidelineFromEnd(0.1f) + val barrierBottom = createBottomBarrier(text1Ref, text2Ref, text3Ref) + + val horizontalChain = createHorizontalChain(text1Ref, text2Ref, text3Ref, chainStyle = ChainStyle.Packed) + //val verticalChain = createVerticalChain(text1Ref, text2Ref, text3Ref, chainStyle = ChainStyle.Packed) + + constrain(horizontalChain) { + start.linkTo(guidelineStart, margin) + end.linkTo(guidelineEnd) + } + /*constrain(verticalChain) { + }*/ + + /* constrain(text2Ref) { + top.linkTo(parent.top) + start.linkTo(text1Ref.end) + } + + constrain(text3Ref) { + top.linkTo(parent.top) + start.linkTo(text2Ref.end) + }*/ + + constrain(text4Ref) { + top.linkTo(barrierBottom) + start.linkTo(text1Ref.start) + } + } +} + +@Preview +@Composable +fun PreviewComposeDemo() { + ComposeDemo() +} +@Preview(device = "spec:parent=pixel_5,orientation=landscape") +@Composable +fun PreviewComposeDemoLandscape() { + ComposeDemo() +} \ No newline at end of file diff --git a/app/src/main/java/com/demo/composeapplication/ui/screens/ViewPagerScreen.kt b/app/src/main/java/com/demo/composeapplication/ui/screens/ViewPagerScreen.kt new file mode 100644 index 0000000..aa0982d --- /dev/null +++ b/app/src/main/java/com/demo/composeapplication/ui/screens/ViewPagerScreen.kt @@ -0,0 +1,186 @@ +package com.demo.composeapplication.ui.screens + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.background +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.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.PageSize +import androidx.compose.foundation.pager.PagerDefaults +import androidx.compose.foundation.pager.PagerSnapDistance +import androidx.compose.foundation.pager.VerticalPager +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshotFlow +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import kotlinx.coroutines.launch + +@OptIn(ExperimentalFoundationApi::class) +@Composable +fun HorizontalPagerScreen() { + val pagerState = rememberPagerState { + 10 + } + var displayedPagePosition by remember { + mutableIntStateOf(0) + } + LaunchedEffect(key1 = pagerState) { + snapshotFlow { + pagerState.currentPage + }.collect{ + displayedPagePosition = it + } + } + val scope = rememberCoroutineScope() + Column { + Text(text = "Current page is $displayedPagePosition") + Button(onClick = { + scope.launch { + var currentPage = pagerState.currentPage + if(currentPage > 0) { + currentPage-- + } + pagerState.scrollToPage(currentPage) + } + }) { + Text(text = "Previous") + } + Button(onClick = { + scope.launch { + var currentPage = pagerState.currentPage + if(currentPage < 10) { + currentPage++ + } + pagerState.scrollToPage(currentPage) + } + }) { + Text(text = "Next") + } + + Box { + HorizontalPager(state = pagerState, + contentPadding = PaddingValues(50.dp), + pageSpacing = 20.dp, modifier = Modifier, + flingBehavior = PagerDefaults.flingBehavior(state = pagerState, pagerSnapDistance = PagerSnapDistance.atMost(4))) { + Row(modifier = Modifier + .background(Color.Red) + .fillMaxSize(), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically) { + Text(text = "Page ${pagerState.currentPage}") + } + } + Row(modifier = Modifier.align(Alignment.BottomCenter)) { + repeat(10){ + val color = if(pagerState.currentPage == it) Color.Black else Color.Gray + Box( + Modifier + .padding(5.dp) + .clip(CircleShape) + .background(color) + .size(18.dp) + ) + } + } + } + } +} + +@OptIn(ExperimentalFoundationApi::class) +@Composable +fun VerticalPagerScreen() { + val pagerState = rememberPagerState { + 10 + } + var displayedPagePosition by remember { + mutableIntStateOf(0) + } + LaunchedEffect(key1 = pagerState) { + snapshotFlow { + pagerState.currentPage + }.collect{ + displayedPagePosition = it + } + } + val scope = rememberCoroutineScope() + Column { + Text(text = "Current page is $displayedPagePosition") + Button(onClick = { + scope.launch { + var currentPage = pagerState.currentPage + if(currentPage > 0) { + currentPage-- + } + pagerState.scrollToPage(currentPage) + } + }) { + Text(text = "Previous") + } + Button(onClick = { + scope.launch { + var currentPage = pagerState.currentPage + if(currentPage < 10) { + currentPage++ + } + pagerState.scrollToPage(currentPage) + } + }) { + Text(text = "Next") + } + + Box { + VerticalPager(state = pagerState, + contentPadding = PaddingValues(50.dp), + pageSpacing = 20.dp, modifier = Modifier, + flingBehavior = PagerDefaults.flingBehavior(state = pagerState, pagerSnapDistance = PagerSnapDistance.atMost(4))) { + Row(modifier = Modifier + .background(Color.Red) + .fillMaxSize(), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically) { + Text(text = "Page ${pagerState.currentPage}") + } + } + Row(modifier = Modifier.align(Alignment.BottomCenter)) { + repeat(10){ + val color = if(pagerState.currentPage == it) Color.Black else Color.Gray + Box( + Modifier + .padding(5.dp) + .clip(CircleShape) + .background(color) + .size(18.dp) + ) + } + } + } + } +} + +@Preview +@Composable +fun PreviewHorizontalPagerScreen() { + HorizontalPagerScreen() +} +@Preview +@Composable +fun PreviewVerticalPagerScreen() { + VerticalPagerScreen() +} \ No newline at end of file