🎨 내비게이션
🎨 내비게이션
모든 앱에는 홈 화면이 있으며, 홈 화면은 앱이 실행된 직후 스플래시 화면이 표시된 뒤 나타난다.
홈 화면에서 사용자는 일반적으로 태스크를 수행하고, 그 결과로 다른 화면이 나타난다. 이 화면들은 보통 프로젝트 안에서 다른 컴포저블의 형태를 갖는다.
아래 내비게이션 그래프를 보자.
홈 화면을 포함해 앱을 구성하는 각 화면은 목적지라 불리며, 일반적으로 하나의 컴포저블 또는 액티비티이다. 안드로이드 내비게이션 아키텍처에서는 내비게이션 백 스택을 이용해 앱 안에서 목적지에 이르는 사용자의 경로를 추적한다. 앱이 처음 실행되는 홈 화면이 현재 목적지가 되고, 사용자가 다른 목적지로 이동하면 해당 화면이 현재 목적지가 되고, 홈 목적지 위의 백 스택에 쌓인다. (사용자가 이동할 때마다)
목적지 사이의 이동과 내비게이션 스택 관리와 관련된 모든 작업은 하나의 내비게이션 컨트롤러에 의해 처리되며, 이 컨트롤러는 NavHostController 클래스에서 제공된다. 또한 수동으로도 스택에서 컴포저블을 꺼내서 사용자가 현재 화면에서 뒤로 돌아갔을 때 스택의 낮은 위치에 있는 화면을 반환하도록 할 수 있다. 내비게이션 아키텍처 컴포넌트를 이용하면 매우 직관적인 절차에 따라 안드로이드 프로젝트에 내비게이션을 추가할 수 있다. 내비게이션 호스트, 내비게이션 그래프, 내비게이션 액션과 직접 작성하는 최소한의 코드를 이용해 내비게이션 컨트롤러 인스턴스에 대한 참조를 얻고 상호작용하도록 할 수 있다.
내비게이션 호스트는 액티비티의 사용자 레이아웃에 추가되는 특별한 컴포넌트로, 사용자가 이동할 목적지의 플레이스홀더 역할을 한다.
composable() 메서드를 호출하고 경로화 목적지를 전달해 내비게이션에 목적지를 추가할 수 있다.
sealed 클래스를 이용하면 단일 위치를 이용해 경로를 변경할 수 있고, 구문 검증이 포함되므로 NavHost를 만들거나 내비게이션을 수행할 때 경로의 오타를 피할 수 있다. (좀 더 유연하게 경로를 정의.)
버튼을 클릭하면
1. 현재 목적지에 대한 백 스택 항목이 만들어진다.
2. 현재 selectedCustomer 상탯값이 백 스택 항목에 저장된다.
3. 백 스택 항목이 백 스택에 추가된다.
4. NavHost 선언 안의 구매 경로에 대한 composable() 메서드가 호출된다.
5. composable() 메서드의 후행 람다가 백 스택 항목에서 인수를 추출해 Purchases 컴포저블에 전달한다.
🎨 하단 내비게이션 바
하단 내비게이션 바는 화면의 가장 아래쪽에 나타나며 내비게이션 아이템 리스트를 표시한다. 각 아이템을 클릭하면 현재 액티비티 안에서 다른 화면 사이를 이동한다.
하단 내비게이션 바의 핵심 컴포넌트는 컴포즈의 BottomNavigation과 BottomNavigationItem 컴포넌트다.
컴포즈 내비게이션 - NavigationDemo 프로젝트 만들기
하단 내비게이션 바 - BottomBarDemo 프로젝트 만들기
🎨 제스처 감지하기
제스처는 터치 화면과 사이에서 발생하는 인접한 일련의 상호작용이다. 전형적인 제스처는 화면 터치에서 시작해 마지막 손가락이나 포인팅 기기가 디스플레이 표면에서 떨어지면 종료된다.
젯팩 컴포즈는 애플리케이션에서 일반적인 제스처를 식별하는 메커니즘을 제공한다.
탭, 더블탭, 롱 프레스, 드래그 또는 멀티 터지를 이용한 축소, 회전 등 다양한 제스처가 있다.
두 가지 제스처 감지 방법을 제공.
1. 제스처 감지 모디파이어를 이용하는 방법으로, 이 모디파이어는 내장 시각 효과를 이용한 제스처 식별 기능을 제공한다.
2. PointerInputScope 인터페이스가 제공하는 함수를 이용하는 방법으로, 추가 코딩을 해야 하지만 좀 더 뛰어난 제스처 감지 능력을 제공한다.
GestureDemo 프로젝트 만들기
클릭 제스처는 clickable 모디파이어를 이용해 모든 보이는 컴포저블에서 감지할 수 있다. 이 모디파이어는 후행 람다를 포함한다. 후행 람다는 적용된 컴포넌트에서 클릭이 감지되었을 때 실행될 코드를 포함한다.
간단한 클릭 제스처를 감지할 때는 clickable 모디파이어가 유용하나, 이는 탭, 프레스, 롱 프레스, 더블탭 등을 구분하지 못한다. 이들을 구분하기 위해서는 PointerInputScope의 detectTapGestures() 함수를 활용해야 한다.
드래그 제스처 감지를 위해 draggable() 모디파이어를 적용하면 컴포넌트에서의 드래그 제스처를 감지할 수 있다. 움직임이 시작된 위치로부터의 오프셋을 상태로 저장한다. 이 인스턴스는 rememberDraggableState() 함수를 호출해서 만든다. 이 상태를 이용해 이후 제스처의 좌표로 드래그된 컴포넌트의 위치를 움직인다. draggable()을 호출할 때는 수직/수평 제스처 감지 여부를 전달한다.
PointerInputScope의 detectDragGestures 함수를 이용하면 수직 및 수평 동시 조작을 지원한다.
scrollable() 모디파이어를 이용하면 리스트 컴포넌트 외에도 스크롤 제스처를 적용할 수 있다. draggale() 모디파이어와 마찬가지로 scrollable()은 수평 또는 수직 방향의 제스처만 지원하지만 모디파이어 선언의 형태가 동일하지 않다. scrollable 상태는 rememberScrollableState() 함수를 이용해 관리되며, 람다를 이용해 스크롤 제스처에 의해 이동하는 거리에 접근할 수 있다. 오프셋값은 계층 안에 존재하는 하나 이상의 오프셋을 조정하는 데 이용된다.
꼬집기 제스처는 일반적으로 콘텐츠의 크기(비율)를 변경하거나 확대 또는 축소 효과를 나타낼 때 이용한다. 이런 타입의 제스처들은 transformable() 모디파이어를 통해 감지한다. 이 모디파이어에는 TransformableState 타입의 상태를 파라미터로 전달해야 하며, 이 상태 인스턴스는 rememberTransformableState() 함수를 호출해서 만들 수 있다. 이 함수가 받는 후행 람다는 3개의 파라미터를 받음.
scaleChange - 하나의 부동소수점값, 꼬집기 제스처가 수행될 때 업데이트된다.
offsetChange - 현재 x, y 오프셋값을 포함하는 하나의 offset 인스턴스, 제스처에 의해 대상 컴포넌트가 이동(트랜지션)할 때 업데이트된다.
rotationChange - 하나의 부동소수점값, 희전 제스처를 감지했을 때 현재 각도를 나타낸다.
변환은 한 컴포넌트의 위치 변경을 포함한다. 변환 제스처는 초기화를 위해 박스 안의 2개의 접촉 포인트가 필요하기 때문에 기기에서만 동작한다. 또한 팬 제스처를 수행했으므로 박스는 제스처 움직임과 반대 방향으로 이동한다.
🎨 스와이프 제스처 감지하기
스와이프 제스처는 기기 화면에 접촉한 지점에서의 수평 또는 수직의 움직임을 의미한다. 이 움직임은 일반적으로 사용자 인터페이스 컴포넌트와 연관이 있으며, 컴포넌트는 스와이프 모션에 따라 움직인다. 스와이프 모션에 필요한 앵커는 스와이프 축을 따라 화면에 존재하는 고정된 위치를 의미한다. 두 앵커 사이의 한 지점은 임계점으로 선언된다.
swipeable() 모디파이어를 대상 컴포저블에 적용해 스와이프 제스처를 감지할 수 있다.
호출 시 지정 가능한 주요 파라미터들
state: SwipeableState - 재구성을 하는 동안 swipeable 상태를 저장하기 위해 이용하면 rememberSwipeableState() 함수를 호출해서 얻는다. 두 위치 변경 가능하다.
anchors: Map - 맵 선언으로 앵커 지점들과 상태들을 연결. 방향 설정에 따라 수평 도는 수직 평면의 픽셀 위치로 지정함.
orientation: Orientation - 스와이프 제스처의 방향을 나타낸다. Orientation.Horiziontal 또는 Orientation.Vertical 중 하나로 선언해야 한다.
enabled: Boolean - 선택 설정사항이며 기본값은 true다. 스와이프 감지 활성화 여부를 나타낸다.
reverseDirection: Boolean - 선택 설정사항이며 기본값은 false다. true로 설정하면 스와이프 방향 효과를 뒤집는다. 다시 말해, 아래쪽 방향 스와이프는 위쪽 방향 스와이프, 오른쪽 방향 스와이프는 왼쪽 방향 스와이프처럼 동작한다.
threasholds: ResistanceConfig? - 선택 설정사항이며 스와이프 모션이 앵커 앱의 첫 번째 또는 마지막 앵커를 넘었을 때 적용할 저항을 정의한다. 기본적으로 스와이프는 앵커로 되돌아오기 전 경계를 약간 넘을 수도 있다. null로 설정하면 스와이프는 경계를 넘어 늘어날 수 없다.
velocityThreshold: Dp - 선택 설정사항이며, 스와이프 속도가 다음 상태로 이동하기 위해 넘어야 하는 단위 속도를 정의한다.
앵커 맵 선언하기
스와이프 앵커는 맵 객체로 선언되며 앵커 위치와 상태의 짝을 포함한다. 앵커들은 부동소수점 위치 픽셀값을 이용해 선언하며, swipeable() 모디파이어가 적용된 컴포저블을 기준으로 x, y 축의 위치를 나타낸다. 일치하는 상태는 Bundle 클래스가 제공하는 모든 유효한 상태 타입을 이용할 수 있다.
임계점은 람다로 선언되며, 람다가 호출될 때 상탯값들을 전달하고 ThresholdConfig 값을 반환해야 한다. ThresholdConfig 인스턴스는 FractionalThreshold() 또는 FixedThreshold() 함수를 호출해서 만들 수 있다.
스와이프 또한 컴포넌트를 자동으로 이동시키지 않는다.