목차
1. 다양한 폼 팩터에 대응하기 위한 작업
1-1) ConstraintLayout 사용
1-2) 넓은 화면용 대체 레이아웃 개발
1-3) 나인 패치 리소스 사용
1-4) 다양한 기기 테스트
2. 폴더블폰 이슈 발생과 해결
2-1) 이슈 발생
2-2) 이슈 해결
안드로이드 기기는 큰 화면, 태블릿, 폴더블과 같이 매우 다양한 폼팩터로 제공됩니다. 다양한 기기에 대응하기 위해 유연한 레이아웃을 개발해야 합니다. 다양한 폼 팩터에 대응하는 UI를 만들기 위한 팁과 작업했던 내용을 기록합니다.
다양한 폼 팩터에 대응하기 위한 작업
1. ConstraintLayout 사용
'Constraint'는 제약이라는 의미입니다. View에 제약 조건을 걸어 배치할 수 있는 레이아웃입니다. ConstraintLayout을 사용하면 레이아웃에 있는 다른 뷰와의 공간적 관계에 따라 각 뷰의 위치와 크기를 지정할 수 있습니다. 이러한 방식으로 화면 크기가 변경될 때 모든 뷰가 함께 이동하고 확장할 수 있습니다. 또한 복잡한 레이아웃을 단순한 계층 구조로 표현할 수 있습니다.
ConstraintLayout은 다양한 제약을 제공합니다. 필요에 따라 여러 종류의 제약을 다양하게 조합해서 사용할 수 있습니다.
Relative positioning | 요소 간 상대 위치 지정. (left, right, top, bottom, start, end, baseline) |
Margins | 요소 간 여백(Margin) 설정을 위한 제약. |
Centering positioning | 뷰를 부모 레이아웃 또는 제약 영역의 중앙에 배치. |
Circular positioning | 대상 뷰를 기준으로 각도(angle)와 반지름(radius)으로 상대 위치 지정. |
Visibility behavior | 뷰의 Visibility 상태에 따른 최종 위치 결정 및 여백. |
Dimension constraints | 뷰에 적용된 제약에 따른 뷰의 크기(Dimension) 결정. |
Chains | 수평 또는 수직 방향(Axis)으로 나열된 뷰에 대한 그룹화. 배치 스타일 지정. |
Virtual Helpers objects | 레이아웃 내 효율적인 뷰 배치에 사용 가능한 몇 가지 Helper 객체들. (Guideline, Barrier, Group) |
Optimizer | 제약 카테고리에 대한 최적화. |
몇 가지 예시를 들어보겠습니다.
부모 뷰에 비례한 뷰의 크기 지정
ex) 부모 뷰의 0.5배 width
android:layout_width="0dp"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.5"
가로/세로 비율 지정
ex) width를 기준으로 1:1 비율
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="1:1"
ex) height를 기준으로 1:3 비율
android:layout_width="0dp"
app:layout_constraintDimensionRatio="W,1:3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
주어진 비율만큼 한 방향으로 치우치게 지정
ex) 왼쪽 사이드 0, 오른쪽 사이드 1 기준으로 0.8 비율에 위치
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_bias="0.8"
2. 넓은 화면용 대체 레이아웃 개발
레이아웃은 항상 해당 뷰를 유연하게 설계해 다양한 화면 크기에 반응해야 하지만 이것만으로는 모든 화면 크기에 최상의 사용자 환경을 제공하지 못할 수도 있습니다. 예를 들어 스마트폰용으로 디자인한 UI는 태블릿에서는 좋은 환경을 제공하지 못할 수 있습니다. 태블릿이나 폴더블처럼 넓은 화면용은 따로 레이아웃을 분리해 개발하는 것이 좋습니다.
layout xml 분리하기
위 이미지처럼 최소 너비가 600 이상인 경우의 xml을 분리해 개발할 수 있습니다. 이때 불필요하게 UI 동작이 중복되지 않도록 주의해야 합니다. 중복되는 부분은 프래그먼트로 개발해 공통으로 사용하고 넓은 화면용에서 추가되는 부분만 별도로 개발하는 것이 좋습니다.
dimens.xml 분리하기
dimens.xml은 문자열 리소스를 관리하는 string.xml처럼 크기, 마진, 패딩 등을 관리하는 파일입니다. UI에서 바로 dp, sp를 지정해 사용해도 되지만 통일성 있는 관리와 유지 보수를 위해 dimens.xml에서 선언하여 사용하는 것이 좋습니다. 마찬가지로 dimens.xml도 최소 너비가 600 이상인 경우 분리해 개발할 수 있습니다.
3. 나인 패치 리소스 사용
수많은 안드로이드 기기의 다양한 해상도에 맞춰 이미지를 제작하는 것은 무리가 있습니다. 나인 패치는 이미지를 9분할 하여 확대되는 영역과 아닌 영역을 구분해 저장하는 방식입니다. 나인 패치를 이용하면 이미지의 확대되는 영역을 지정해 줌으로써 여러 해상도에 적용하여도 깨지지 않는 이미지를 사용할 수 있습니다.
나인 패치 이미지의 확장자는 .9.png입니다. 이미지를 추가할 때 .9 형식이면 안드로이드에서 자동으로 나인 패치 이미지로 인식합니다.
나인 패치를 만드는 법은 다양합니다. 한 가지 방법으로 http://romannurik.github.io/AndroidAssetStudio/nine-patches.html에서 손쉽게 만들 수 있습니다. Stretch region에서 확대 영역을 지정하고 Content padding에서 콘텐츠 영역을 지정할 수 있습니다.
4. 다양한 기기 테스트
다양한 화면 크기로 앱을 테스트하여 UI 크기 조정이 제대로 이루어졌는지 확인하는 것이 중요합니다. Android Emulator를 사용하여 원하는 화면 크기를 에뮬레이션 할 수 있습니다.
폴더블폰 이슈 발생과 해결
1. 이슈 발생
위 이미지는 진행했던 프로젝트의 메인화면 구조입니다. 메인 배너 이미지의 넓이를 match_parent로 높이는 이미지 비율에 맞춰 wrap_parent로 설정하고 비율 유지를 위해 adjustViewBounds=true 속성을 지정했습니다. 이후 테스트를 해보니 일반적인 모바일 비율에서는 괜찮았으나 폴더블처럼 넓은 화면에서는 아래와 같은 이슈가 발생했습니다.
화면 넓이에 맞춰 높이가 설정되다 보니 이미지 크기가 화면을 꽉 채울 정도로 늘어났고, 확대된 이미지만큼 아래에 있는 뷰들이 더 아래쪽으로 이동해 첫 메인화면에 접속했을 때 보여야 할 부분들이 가려졌습니다.
2. 이슈 해결
1. 넓은 화면일 경우 이미지 뷰만 사이즈 조절하기
2. 넓은 화면일 경우 넓은 화면용 레이아웃 보여주기
3. 분할된 멀티뷰 사용하기
당시의 상황은 스케줄 상 출시가 얼마 남지 않은 빡빡한 일정이었고, 화면 디자인이 자주 변경되는 상황이었습니다. 이슈를 해결할 여러 방법 중 상황에 가장 맞는다고 판단되는 방법으로 해결하였습니다. 1번의 경우 가장 손쉽게 해결할 수 있는 방법이지만 추후 디자인이 변경된다면 수정할 부분이 더 복잡해질 것 같아 유지 보수를 고려해 패스하였습니다. 3번의 경우 멀티뷰를 위한 UI 디자인이 새롭게 별도로 필요했고 멀티 뷰에서 아이템 클릭 시 이동, 뒤로 가기 처리 등 테스트해야 할 부분과 예외 처리할 것들이 많아 패스하였습니다. 빠르게 개발을 해야 하는 상황 속에서 나중에 디자인이 변경될 때를 고려하여 넓은 화면용 레이아웃을 분리해 따로 관리하는 편이 낫다고 판단했고 최종적으로 2번을 선택했습니다.
최소 너비가 600 이상의 넓은 화면용 레이아웃을 새로 분리해 개발하여 폴더블과 같은 화면에서 넓은 화면용 디자인이 적용되도록 하였습니다. 또한 넓은 화면 전용 배너와 콘텐츠 이미지를 서버에 저장해두고 api를 요청할 때 디바이스 크기를 전달해 넓은 화면용 이미지를 응답받았습니다.
넓은 화면일 때 최종 결과물은 아래와 같은 구조로 완성되었습니다. 추후 관리자 웹에 넓은 화면용 이미지를 추가하는 기능도 개발하였습니다.
(추가 - 멀티뷰 사용하기)
SlidingPaneLayout를 이용해 폴더블용 멀티뷰를 만들 수도 있습니다. SlidingPaneLayout은 Jetpack Window Manager를 사용하며, 공간이 있는 경우 두 개의 창을 나란히 표시하고 그렇지 않은 경우 창을 포개서 첫 번째 창만 표시되도록 자동으로 조정합니다.
SlidingPaneLayout에 fragment를 사용해 개발한 예제입니다. 아래 깃허브 링크를 참고해 주세요 :)
방문해 주셔서 감사합니다^^
잘 읽으셨다면 좋아요❤ 눌러주세요!ㅎㅎ
'Main' 카테고리의 다른 글
[Android] Custom Recyclerview (18) | 2023.01.10 |
---|---|
[Android] 이미지 로드 최적화 (10) | 2023.01.06 |
[Android] Github Actions으로 CI/CD 구축 (8) | 2022.12.21 |
[Android] Room을 활용해 Android 오프라인 캐시 구현 (0) | 2022.12.06 |
[Android] Service를 활용한 Timer 개발 (0) | 2022.11.30 |
댓글