Study Record

[안드로이드] SlidingPaneLayout 살펴보기 본문

안드로이드

[안드로이드] SlidingPaneLayout 살펴보기

초코초코초코 2023. 8. 3. 23:03
728x90

😶 SlidingPaneLayout 패턴

Android 가 사용되는 기기는 핸드폰뿐만 아니라 태블릿, 데스크톱 등에서 사용될 수 있다. 이에 기기에 맞게 화면을 재구성해야 할 때가 있다. SlidingPaneLayout 은 화면을 재구성하기 쉽게 도와주는 Layout 이다.

 

예를 들어, 목록 List View 가 있고 그 List 의 항목을 클릭하면 세부 정보를 보여주는 View 가 있을 수 있다. 이것을 화면이 작은 핸드폰과 같은 기기에서는 List 항목을 보여주는 화면과 세부 정보를 보여주는 화면으로 나눠 보여준다. 화면이 좀 큰 태블릿 같은 경우에는 두 분할로 나눠 한쪽에는 목록 정보를 보여주고 나머지 한쪽에는 그 목록의 세부 정보를 보여주도록 화면을 구성할 수 있다.

 

 

 

😶 창 분할 기준

화면이 작으면 2개의 창을 각각 하나씩 보여주고 2 개의 창의 최소 크기보다 크면 하나의 화면에 2개의 화면을 분할하여 보여준다. 장치의 표준이 되는 크기가 있는데 그건 다음 표와 같다.

 

너비(Width) BreakPoint 장치 표준
Compact Width < 600dp 핸드폰 세로 모드
Medium width 600dp + 테블릿의 세로모드
Expanded with 840dp +   테블릿의 가로모드

 

 

 

😶 Library Dependencies

dependencies {
    ...
    implementation "androidx.slidingpanelayout:slidingpanelayout:1.2.0"
}

 

 

😶 SlidingPaneLayout 배치하기

SlidingPaneLayout 를 부모로 창으로 사용할 2개의 View 혹은 ViewGruop 을 Child 로 둔다.

<androidx.slidingpanelayout.widget.SlidingPaneLayout
    android:id="@+id/sliding_pane_layout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SportsListFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="550dp"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:padding="8dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

    <androidx.fragment.app.FragmentContainerView
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:id="@+id/detail_container"
        android:layout_weight="1"
        android:name="com.example.android.sports.NewsDetailsFragment"/>
</androidx.slidingpanelayout.widget.SlidingPaneLayout>

목록 리스트를 보여주는 recycler_view 와 목록을 클릭하면 세부 사항을 보여주는 detail_container 를 SlidingPaneLayout 의 child 로 배치했다. 두 번째 창의 layout_weight 를 1로 준 이유는 현재 2개의 창은 880dp 를 차지한다. 880dp 보다 큰 너비를 가진 장치라면 남은 공간만큼 빈틈으로 보일 것이기 때문에 layout_weight = 1 로 하면 세부 사항 창이 나머지 공간을 전부 차지하면서 자연스럽게 2 분할 화면으로 보인다.

 

 

😶 창 전환

너비가 큰 태블릿 화면이면 한 화면에 2창 모두 배치된 상태이니 창 전환과 관련된 함수를 실행해도 영향을 받지 않는다. SlidingPaneLayout 안에 배치한 창 2개는 선언한 순서대로 왼쪽에서 오른쪽으로, 첫 번째 화면과 두 번째 화면으로 나뉜다.

 

너비가 작은 핸드폰 화면에는 첫 번째 화면이 먼저 차지하고 있을 것이다 여기서 두번째 화면으로 전환하고 싶다면 openPane() 함수를 실행하고 두번째 화면에서 첫번째 화면으로 돌아갈 땐, closePane() 함수를 실행한다.

binding.slidingPaneLayout.openPane()
binding.slidingPaneLayout.closePane()

함수를 실행하고 화면이 전환될 때 애니메이션 효과가 자동으로 설정되어 있다.

 

 

😶 뒤로 가기 혹은 Back button 관리

너비가 작은 핸드폰과 같은 기기는 첫 번째 창과 두번째 창이 다른 화면으로 존재하며 만약 두번째 화면에서 뒤로 가기 버튼을 누르면 첫번째 화면으로 돌아가는 것이 자연스럽다. 이와 관련해서 명시된 것이 없으면 두번째 화면이어도 뒤로 가기 버튼을 누르면 첫번째 화면으로 돌아가지 않는다. (back Stack 에 명시된 바가 없으면 종료되고 명시된 정보가 있다면 그곳으로 돌아간다.)

 

Back Button 을 관리하는 방법은 OnBackPressedCallback 를 사용한다.

 

먼저, OnBackPressedCallback 을 상속받는 Callback 클래스를 생성한다. 

class SlidingPanelOnBackPressedCallback(
    private val slidingPaneLayout: SlidingPaneLayout
) : OnBackPressedCallback(slidingPaneLayout.isSlideable && slidingPaneLayout.isOpen) {

    override fun handleOnBackPressed() {
        slidingPaneLayout.closePane()
    }
}

OnBackPressedCallback 의 생성자의 slidingPaneLayout.isSlideable 의 의미는 창 전환을 할 수 있는지(true/false)를 의미하는데 핸드폰과 같은 너비가 작아 한 화면에 두 개의 창을 배치할 수 없는 경우에만 true 를 갖는다. slidingPaneLayout.isOpen 은 창전환이 가능할 때, 현재 창지 두 번째 창일 때 true 를 갖는다. 따라서, 창 전환을 할 수 있고 현재 화면이 두번째 창일 경우에만 callback 이 가능하다.

handleOnBackPressed() 함수는 뒤로 가기 버튼을 눌렀을 때 위의 생성자에서 CallBack 이 가능할 때 호출되는 함수로 여기서 첫 번째 화면으로 이동하는 함수(closePane())를 실행함으로써 두번째 화면에서 뒤로가기 버튼을 누르면 첫번째 화면으로 돌아간다.

 

SlidingPanelLayout.PanelSlideListener 를 상속받으면 open 될 때와 close 될 때를 호출받을 수 있는데 이때 isEnabled 를 true 로 하면 OnBackPressedCallback 의 callBack 을 가능(Enable)하고 false 로 하면 callBack 이 불가능하다.

class SlidingPanelOnBackPressedCallback(
    private val slidingPaneLayout: SlidingPaneLayout
) : OnBackPressedCallback(slidingPaneLayout.isSlideable && slidingPaneLayout.isOpen),
    SlidingPaneLayout.PanelSlideListener {

    init {
        slidingPaneLayout.addPanelSlideListener(this)
    }

    override fun handleOnBackPressed() {
        slidingPaneLayout.closePane()
    }

    override fun onPanelSlide(panel: View, slideOffset: Float) {
    }

    override fun onPanelOpened(panel: View) {
        isEnabled = true
    }

    override fun onPanelClosed(panel: View) {
        isEnabled = false
    }
}

 

 

OnBackPressedCallback 을 이제 Back Press 를 관리하는 OnBackPressedDispatcher 에 Callback 을 등록해야 한다.

OnBackPressedDispatcher 는 FragmentActivity 객체로 접근할 수 있다.

requireActivity().onBackPressedDispatcher.addCallback(
   viewLifecycleOwner,
   SlidingPanelOnBackPressedCallback(slidingPaneLayout)
)

첫 번째 인자로 받은 LifecycleOwner 로 Lifecycle.State.STARTED 인 경우에만 OnBackPressedDispatcher 에 callback 을 추하고 LifcycleOwner 가 파괴되면 등록된 callback 을 제거한다.

 

 

😶 Lock Mode

SlidingPaneLayout 은 너비가 작은 화면일 때 창 전환이 가능한 경우 따로 gesture navigation 을 사용하지 않아도 스와이프로 창 전환을 할 수 있다. 이것을 원치 않을 경우 다음과 같이 lockMode 값을 LOCK_MODE_LOCKED 로 설정하면 된다.

slidingPaneLayout.lockMode = SlidingPaneLayout.LOCK_MODE_LOCKED

 

 

 

 

 

맞춤 뒤로 탐색 기능 제공  |  Android 개발자  |  Android Developers

맞춤 뒤로 탐색 기능 제공 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 뒤로 탐색 기능은 사용자가 이전에 방문한 화면 기록을 통해 뒤로 이동하는 기능

developer.android.com

 

SlidingPaneLayout  |  Android Developers

 

developer.android.com

 

 

Create a two pane layout  |  Android Developers

Create a two pane layout Stay organized with collections Save and categorize content based on your preferences. Try the Compose way Jetpack Compose is the recommended UI toolkit for Android. Learn how to work with layouts in Compose. Every screen in your a

developer.android.com

 

반응형 레이아웃으로 UI 이전  |  Android 개발자  |  Android Developers

반응형 레이아웃으로 UI 이전 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Android 앱은 끊임없이 확장되는 기기 폼 팩터 생태계를 지원해야 합니다. 앱의 UI

developer.android.com

 

 

 

728x90