코틀린 & 컴포즈 & Java/컴포즈 Compose

[Compose] 컴포즈 실전 내가 경험한 Tip !

코딩하는후운 2025. 2. 25. 17:43
반응형

mutableStateOf 사용시 유의할 점

  1. @Composable함수 내에서 mutableStateOf를 사용할 때, remember를 사용해야 한다.
  2. mutableStateOf<Int> 대신 mutableIntStateOf를 사용하는 것이 더 성능이 좋다 (린트 경고)

Compose 매개변수 정렬 규칙

  1. 필수 매개변수 (State 포함)
  2. 이벤트 핸들러 (onClick, onChange 등)
    1. 이벤트 핸들러는 “발생할 때”를 의미하기 때문에 현재형을 사용해야 함.
  3. modifier: Modifier = Modifier
  4. 기본값을 가진 선택적 매개변수
  5. content: @Composable () -> Unit (Trailing Lambda, 선택적)

예외 사항 (Trailing Lambda)

Compose에서 onClick: () -> Unit 같은 이벤트 핸들러를 마지막 매개변수로 두면, Compose가 content 슬롯과 헷갈릴 가능성이 있음.
이 경우, MyButton("Click Me") {}처럼 호출하면, onClick이 아니라 UI content를 전달하는 것처럼 보일 수 있음!

Compose에서는 onClick을 마지막에 두지 않는 다고 함.
→ 이 경우(매개 변수와, 이벤트 핸들러만 있을 경우) : 매개변수 앞에, 이벤트 핸들러를 둔다.


Composable 함수 내에 과거형 이벤트명을 사용하면 안 되는 이유

  1. 이벤트는 상태(State)가 아니라 동작(Action)이다
  • onClicked, onLoaded 같은 과거형 이벤트명은 이미 발생한 이벤트처럼 보이기 때문에, UI에서 이벤트를 처리하는 것이 아니라 단순히 상태를 읽는 것처럼 오해할 수 있습니다.
  • 이벤트는 일반적으로 현재 발생하는 동작을 나타내야 하므로, onClick, onLoad 같은 현재형으로 표현하는 것이 적절합니다.
  1. 이벤트 핸들러가 비동기 처리될 수 있음
  • 현재형 이벤트명을 사용하면 이벤트가 발생하는 순간을 의미하는 것임을 명확하게 전달할 수 있습니다.
  1. 명령형 표현이 아니라 선언형(Declarative) UI에 맞추기 위해
  • onClicked() 같은 과거형 이벤트명은 이벤트가 UI에서 직접 실행되는 것처럼 보이므로 선언형 패러다임에 맞지 않습니다.

MutableState를 @Composable 함수의 매개변수로 직접 전달하면 안 된다는 Compose의 규칙이 있다.

문제점:

  1. Composable 내부에서 상태를 직접 변경할 수 있어, 부모-자식 간의 책임이 모호해짐.
  2. 부모와 자식이 MutableState를 공유하면 예측하기 어려운 사이드 이펙트가 발생할 수 있음.
  3. State Hoisting 원칙을 위반하여, 상태를 Composable 함수가 직접 가지게 됨.

Modifier를 여러 개의 Composable에 재사용하면 발생하는 문제

  • Modifier는 각 Composable마다 새로운 Modifier 인스턴스를 만들어서 사용해야 한다는 Compose의 규칙

Composable 함수가 최상위 수준에서 여러 개의 UI 요소를 직접 반환할 때 발생하는 문제

  • Composable 함수는 하나의 UI 루트만 반환해야 하는데, 여러 개의 요소를 동시에 배치하면 안된다.

TextField 입력시 왜 하단에 여백이 생기는가?

1. TextField의 내부 패딩

기본 TextField는 내부적으로 BasicTextField를 래핑하고 있으며, 기본 패딩이 포함되어 있다.이 때문에 입력 텍스트가 위쪽으로 쏠리거나, 하단에 여백이 남을 수 있다.

2. lineHeight을 조정해도 해결되지 않음

보통 TextStyle에서 lineHeight을 조정하면 텍스트 정렬이 맞을 거라고 생각하지만, Compose에서는 Baseline기준으로 텍스트를 정렬하기 때문에 lineHeight만 조정해도 하단 여백이 남을 수 있다.

3. TextField의 높이를 강제 지정하는 경우

modifier.height() 또는 modifier.heightIn()을 사용할 경우, 내부 정렬이 깨지면서 텍스트가 위쪽으로 몰릴 수 있다.

해결 방법

wrapContentHeight() 사용

wrapContentHeight()를 사용하면 입력된 텍스트 높이에 맞춰 TextField의 높이가 자동 조정되므로, 위쪽으로 몰리는 문제가 해결된다.

참조 :
https://proandroiddev.com/the-missing-pieces-of-text-alignment-in-compose-text-50efec9bc387


lazyColumn 스크롤 빠르게 했을 때 OverScroll 나면서 스크롤 안되는 이슈

안드로이드 리스트에서 땡겨지는 효과 OverScroll이 있는데
오버스크롤 되었을 때에는 스크롤을 놓아야 그다음 스크롤이 됩니다.

오버스크롤을 없애주자.

아래 코드로 LazyColumn을 감싸서 오버스크롤을 없애주자.

CompositionLocalProvider(
    LocalOverscrollConfiguration provides null,
) {
	LazyColumn(
}

참조 :
https://stackoverflow.com/questions/69468212/remove-lazycolumn-overscroll-effect-in-jetpack-compose


LazyColumn 끝에 여백 붙이기

contentPadding을 이용하여 끝에 여백을 준다.

LazyColumn(
    contentPadding = PaddingValues(bottom = 120.dp),
    modifier = Modifier.background(Color.White),
)

Modifier로 라운드진 배경과 패딩을 넣는 방법

Row (
  modifier = Modifier
      .background(
          color = colorResource(id = R.color.td054),
          shape = RoundedCornerShape(size = 4.dp),
      ).padding(2.dp)
)

Row로 여러개 텍스트 구현시 가운데 텍스트가 길어지면 …되도록 하는법

modifier = Modifier
   .weight(1f, fill = false) // 남은 공간을 적절히 차지, fill을 false로 설정

 

실제 경험 해본 것들을 정리해 보았습니다.

도움이 되시길 바랍니다.!

반응형