-
Notifications
You must be signed in to change notification settings - Fork 0
Compose 적응기
upsk1 edited this page Nov 14, 2023
·
6 revisions
- K034 K039 캠퍼와 미리 기술 상의후
Compose
를 사용하기로 하였습니다! - 두분과는 다르게
Compose
를 완전 처음 접해보는 입장이어서 미리 최대한 학습 하기로 생각하였습니다. - K034 캠퍼에게 페어 프로그래밍으로 지도 받으며 아래와 같은 페이지를 구성해보았습니다.
- 현재는 K039 캠퍼의 조언에 따라 Developer 의 Basics Codelab을 수강하고 있습니다.
- https://developer.android.com/codelabs/jetpack-compose-basics#0
- Codelab 에서 State Hoisting과 lazycolumn, remember에 대한 기초 개념을 학습하였습니다.
@Composable
fun Greeting(name: String) {
var expanded by remember { mutableStateOf(false) }
val extraPadding by animateDpAsState(
targetValue = if (expanded) 48.dp else 0.dp,
label = "",
animationSpec = tween(durationMillis = 2000)
)
Surface(
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
) {
Row(modifier = Modifier.padding(24.dp)) {
Column(
modifier = Modifier
.weight(1f)
.padding(bottom = extraPadding)
) {
Text(text = "Hello,")
Text(text = "$name!")
}
OutlinedButton(onClick = { expanded = !expanded }) {
Text(
text = if (expanded) "Show less" else "Show more",
color = Color.White
)
}
}
}
}
- expanded가 갱신되면 Greeting 함수가 Recomposition이 되고 expnaded 값에 맞게 extraPadding이 갱신됩니다.
- 갱신된 변수들이 뷰 변경 로직에 관여합니다. (Column의 padding + Text의 text)
- by 키워드로 expanded.value가 아닌 expanded로 사용할 수 있습니다.
@Composable
fun MyApp() {
var shouldShowOnboarding by rememberSaveable { mutableStateOf(true) }
if (shouldShowOnboarding) {
OnboardingScreen(onContinueClicked = { shouldShowOnboarding = false })
} else {
Greetings()
}
}
@Composable
fun OnboardingScreen(onContinueClicked: () -> Unit) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Welcome to the Basics Codelab!")
Button(
modifier = Modifier.padding(vertical = 24.dp),
onClick = onContinueClicked
) {
Text("Continue")
}
}
}
- 고차함수 형식으로 MyApp 에서 상태를 변경하는 함수를 OnboardingScreen함수에 넘깁니다.
- 위와 같은 방식을 State Hoisting으로 학습하였습니다.
- Text
Text(
modifier = Modifier.width(300.dp),
color = Color.Red,
text = "안녕하세요",
fontSize = 30.sp,
fontWeight = FontWeight.Bold,
fontFamily = FontFamily.Cursive,
letterSpacing = 3.sp,
maxLines = 2,
textDecoration = TextDecoration.LineThrough,
textAlign = TextAlign.Start
)
- Button
Button(
onClick = onButtonClicked,
enabled = false,
border = BorderStroke(2.dp, Color.Magenta),
shape = CircleShape,
contentPadding = PaddingValues(20.dp)
) {
Icon(
imageVector = Icons.Filled.Send,
contentDescription = null
)
Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))
Text(text = "Send")
}
- Modifier
@Composable
fun Greeting() {
Button(
colors = ButtonDefaults.buttonColors(
containerColor = Color.Magenta,
contentColor = Color.Cyan
),
onClick = {},
modifier = Modifier
.size(
width = 200.dp,
height = 100.dp
)
) {
Icon(
imageVector = Icons.Filled.Search,
contentDescription = null
)
Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))
Text(
"Search",
modifier = Modifier.offset(x = 10.dp)
)
}
- Surface
Surface(
border = BorderStroke(
width = 2.dp,
color = Color.Magenta
),
modifier = Modifier.padding(5.dp),
shadowElevation = 10.dp,
shape = CircleShape,
color = MaterialTheme.colorScheme.primary
) {
Text(
text = "Hello $name!",
modifier = Modifier.padding(8.dp)
)
}
- Box
@Composable
fun Greeting() {
Box(modifier = Modifier.size(100.dp)) {
Box(
modifier = Modifier.matchParentSize()
.background(Color.Cyan)
.align(Alignment.CenterStart)
)
Box(
modifier = Modifier.size(70.dp)
.background(Color.Yellow)
.align(Alignment.BottomEnd)
)
}
- Row
@Composable
fun Greeting() {
Row(
// horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.Bottom, modifier = Modifier
.height(40.dp)
.width(200.dp)
) {
Text(
text = "첫 번째!",
textAlign = TextAlign.End,
modifier = Modifier
.align(Alignment.Top)
.weight(3f)
)
Icon(
imageVector = Icons.Filled.Add,
contentDescription = "추가"
)
Text(
text = "두 번째!",
modifier = Modifier
.align(Alignment.CenterVertically)
.weight(2f)
)
Text(
text = "세 번째!",
modifier = Modifier
.align(Alignment.Bottom)
.weight(2f)
)
}
}
- Column
```kotlin
@Composable
fun Greeting() {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Bottom,
modifier = Modifier.size(100.dp)
) {
Text(
text = "첫 번째",
modifier = Modifier.align(Alignment.CenterHorizontally)
)
Text(text = "두 번째")
Text(
text = "세 번째",
modifier = Modifier.align(Alignment.Start)
)
}
}
- BoxWithConstraints
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyComposeTheme {
Outer()
}
}
}
}
@Composable
fun Outer() {
//Ineer의 width는 200이지만 Column의 width가 150이라 maxW가 150로 설정된다.
Column(modifier = Modifier.width(150.dp)) {
Inner(
Modifier
.height(160.dp)
.width(200.dp)
)
}
}
@Composable
private fun Inner(modifier: Modifier = Modifier) {
BoxWithConstraints(modifier = modifier) {
if (maxHeight > 150.dp) {
Text(
text = "여기 꽤 길군요!",
modifier = Modifier.align(Alignment.BottomCenter)
)
}
Text(text = "maxW: $maxWidth maxH: $maxHeight minW: $minWidth minH: $minHeight")
}
}
@Composable
fun Greeting() {
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
MyComposeTheme {
Outer()
}
}
- Image
Column{
Image(
painter = painterResource(id = R.drawable.kakao_login_large_wide),
contentDescription = "카카오 로그인"
)
Image(
imageVector = Icons.Filled.Settings,
contentDescription = null
)
}
🤔 우리는 왜 이런 선택을 했는가?
김민조
장지호
- VersionCatalog 적용기
- Glide 와 Coil 은 각각 어떻게 이미지를 불러오는가?
- Third-Party-Library 없이 비디오 컷 편집 기능 구현하기
- Ktor 적용기 (feat.Ktor Generics Response Handler)
- ImageCropper 라이브러리 없이 구현하기
- AccessToken 재발급과 예외 처리 (feat.Ktor)
- Third-Party-Library 없이 영상으로부터 빠르게 프레임 추출하기 (feat.YUV)
조준장
- MediaPlayer와 ExoPlayer를 비교해보자!
- 비디오 스트리밍을 최적화 해보자!
- MVI를 뿌셔보자!
- ExoPlayer Lifecycle를 관리해보자!(feat.DisposableEffect)
장민석
하채리