Jetpack Compose Part 2 - Preview / Layout / Decompile
Writers
by 김남훈 @Naver
by 배희성 @RocketPunch
by 송시영 @SmartStudy
by 이기정 @BankSalad
Android Studio의 Jetpack Compose
Android Studio Preview를 사용해 Compose를 사용하다보면 Preview라 코드레벨에서 활성화되는 것을 알 수 있다.
좀 더 자세히 살펴보자.
Preview의 기능들
Preview 와 Compose 를 사용해서 아래와 같이 구성할 수 있다.
Split(design/code) 을 선택에 따라 코드 및 디자인의 패널을 변경할 수도 있다.
미리보기에서 인터렉티브 모드를 설정할 수 있다.
인터렉티브 모드를 설정하면 실제 디바이스처럼 클릭이나 드래그 등의 상호 작용을 확인해 볼 수 있다.
다만, 네트워크나 파일에 접근 또는 일부 Context API 는 인터렉티브 모드를 지원하지 않고 있다.
간헐적으로 interactive 모드가 작동하지 않는 경우가 있다.
미리보기에서 직접 디바이스 혹은 에뮬레이터로 배포하여 결과를 확인할 수도 있다.
@Preview Annotation 분석
위에서 언급했다시피 @Preview를 사용하면 디바이스나 에뮬레이터를 실행하지 않고 실시간으로 Compose UI 를 볼 수 있다.
@Preview를는 아래와 같이 구성되어 있으며 설정에 따라서 미리보기를 다양하게 구성할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
annotationclassPreview( val name: String = "", val group: String = "", @IntRange(from = 1)val apiLevel: Int = -1, // TODO(mount): Make this Dp when they are inline classes val widthDp: Int = -1, // TODO(mount): Make this Dp when they are inline classes val heightDp: Int = -1, val locale: String = "", @FloatRange(from = 0.01)val fontScale: Float = 1f, val showSystemUi: Boolean = false, val showBackground: Boolean = false, val backgroundColor: Long = 0, @UiModeval uiMode: Int = 0, @Deviceval device: String = Devices.DEFAULT )
name : Preview 의 이름을 지정하며, 기본 값은 function 이름으로 설정된다.
group : Preview 의 그룹을 지정한다, 기본 값은 function 이름으로 설정된다.
apiLevel : api level 설정에 따라 Composable 을 렌더링해준다.
widthDp : Preview 의 너비를 설정한다. (기본 단위는 dp)
heightDp : Preview 의 높이를 설정한다. (기본 단위는 dp)
locale : 사용자 locales 에 따라 보여지는 UI 를 테스트 하기 위해 사용한다.
fontScale : 기본 density 애 배율을 적용해서 폰트 사이즈를 변경할 수 있다.
showSystemUi : true 로 설정하면 status bar 와 action bar 를 노출한다.
showBackground : true 로 설정하면 기본 배경색상을 적용해준다.
backgroundColor : 미리보기의 배경색을 설정할 수 있으며, showBackground 설정에 따라 노출 유무를 결정한다.
uiMode : uiMode 를 설정한다.
device : 기존 정의된 디바이스를 프리뷰에 적용한다. Devices object 에 정의된 값을 선택해서 사용할 수 있습니다. (Devices.NEXUS_9)
Compose의 레이아웃 구성
Column : 아이템을 세로로 배치한다.
1 2 3 4 5 6 7
@Composable funComposeColumn() { Column { Text(text = "My First Compose") Text(text = "My First Compose") } }
Row : 아이템을 가로로 배치한다.
1 2 3 4 5 6 7
@Composable funComposeRow() { Row { Text(text = "My First Compose") Text(text = "My First Compose") } }
Box : 구성 요소를 다른 구성 요소 위에 배치한다.
1 2 3 4 5 6 7
@Composable funComposeBox() { Box { Text(text = "My First Compose 1") Text(text = "My First Compose 2") } }
Modifier : 구성 요소의 크기, 마진등을 변경하거나 클릭이나 스크롤 등의 이벤트를 제어할 수 있도록 한다.
if (existingComposeView != null) with(existingComposeView) { setParentCompositionContext(parent) setContent(content) } else ComposeView(this).apply { // Set content and parent **before** setContentView // to have ComposeView create the composition on attach setParentCompositionContext(parent) setContent(content) setContentView(this, DefaultActivityContentLayoutParams) } }
@MustBeDocumented @Retention(AnnotationRetention.BINARY) @Target( // function declarations // @Composable fun Foo() { ... } // lambda expressions // val foo = @Composable { ... } AnnotationTarget.FUNCTION,
// type declarations // var foo: @Composable () -> Unit = { ... } // parameter types // foo: @Composable () -> Unit AnnotationTarget.TYPE,
// composable types inside of type signatures // foo: (@Composable () -> Unit) -> Unit AnnotationTarget.TYPE_PARAMETER,
// composable property getters and setters // val foo: Int @Composable get() { ... } // var bar: Int // @Composable get() { ... } AnnotationTarget.PROPERTY_GETTER ) annotationclassComposable
AnnotationTarget을 통해 메서드나 Lambda 객체를 넘겨서 뷰를 조립하는 방식인데, View와 ViewGroup처럼 내부적으로 트리 구조로 실행지점에 대한 정보를 저장하고 있다.
파면 팔수록 Flutter의 Widget, React Native의 Component와 유사한 느낌을 준다.
Jetpack Compose Part 2 - Preview / Layout / Decompile