본문 바로가기
안드로이드 코틀린

[Kotlin][Android] 트렌디한 SlidingUpPanel Layout 적용하기

by teamnova 2021. 11. 7.

요즘 나온 앱들 중 트랜디한 앱들 대부분이 사용하는 레이아웃 인데요

 

클럽 하우스에서도 보면 하단에 네비게이션 버튼이 나열되어 있지 않고 레이아웃 하나가 밑에서 올라옵니다.

 

바텀 쉬트와 다를게 뭐가 있을까 비교해 보면서 진행해 보면 좀더 재미있겠죠?

 

그럼 SlidingUPPanel Layout을 적용하러 가볼까요?

 

 

http://github.com/hannesa2/AndroidSlidingUpPanel

 

GitHub - hannesa2/AndroidSlidingUpPanel: It provides a simple way to add a draggable sliding up panel (popularized by Google Mus

It provides a simple way to add a draggable sliding up panel (popularized by Google Music and Google Maps) - GitHub - hannesa2/AndroidSlidingUpPanel: It provides a simple way to add a draggable sli...

github.com

 

 

build.gradle (module)

dependencies{
	...
	implements 'com.sothree.slidinguppanel:library:3.4.0'
}

 

먼저 gradle:app 파일에 라이브러리 경로를 추가해주세요.

 

SlidingUpPanel을 사용하려면 최상단의 레이아웃을 다음으로 바꿔야 합니다.

com.sothree.slidinguppanel.SlidingUpPanelLayout

 

SlidingUpPanelLayout은 반드시 두 개의 자녀 뷰를 가지고 있어야 하며, 배경으로 사용될 뷰가 먼저 오게하고, 슬라이드 할 뷰가 뒤에 오게 정렬합니다.

레이아웃 구성

 

SlidingUpPanelLayout은 몇 가지 옵션을 정할 수 있습니다. gravity는 반드시 정해줘야 합니다. 

 

 

android:gravity: 어느 방향에서 드래그 할 것인지 설정 (top, bottom) 필수

app:umanoDragView: 드래그 할 때 사용할 뷰 선택 (기본값: 최상위 레이아웃, 위 이미지의 slide_layout)

app:umanoPanelHeight: 닫혀있을 때 보이는 높이 (기본값: 68dp)

app:umanoOverlay: 슬라이드 패널을  오버레이로 만들지 여부 (기본값: false)

    - true일 경우 슬라이드 패널의 기본 배경색이 투명해지고, 배경 레이아웃의 높이가 화면 크기로 조정된다.

    - false일 경우 슬라이드 패널이 불투명해지고, 배경 레이아웃의 높이가 PanelHeight만큼 줄어든다.

app:umanoFadeColor: 패널이 열려있을 때의 배경 색상 (기본값: 20% 어두워짐)

 

 

 

이 외의 여러 옵션들은 위의 링크 페이지에서 확인하면 되겠죠?

먼저 화면을 구성해 보겠습니다. 

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<com.sothree.slidinguppanel.SlidingUpPanelLayout
    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:id="@+id/main_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:gravity="bottom"
    app:umanoDragView="@id/slide_layout">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/back_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#42A5F5">

        <TextView
            android:id="@+id/tv_text1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Background Layout"
            android:textColor="?android:attr/textColorPrimaryInverse"
            android:textSize="18sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/slide_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <Button
            android:id="@+id/btn_touch"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="16dp"
            android:text="터치잠금"
            app:layout_constraintBottom_toBottomOf="@+id/btn_toggle"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="@+id/btn_toggle" />

        <Button
            android:id="@+id/btn_toggle"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:text="열기"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/btn_enable"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:text="비활성화"
            app:layout_constraintBottom_toBottomOf="@+id/btn_toggle"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/btn_toggle" />

        <TextView
            android:id="@+id/tv_slideText1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="128dp"
            android:text="slideOffset"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/tv_slideOffset"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:text="TextView"
            android:textColor="?android:attr/textColorPrimary"
            android:textSize="18sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tv_slideText1" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</com.sothree.slidinguppanel.SlidingUpPanelLayout>

 

 

 

MainActivity.kt

 

class MainActivity : AppCompatActivity() {
    private lateinit var binding : ActivityMainBinding  // 뷰 바인딩
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)
 
        val slidePanel = binding.mainFrame                      // SlidingUpPanel
        slidePanel.addPanelSlideListener(PanelEventListener())  // 이벤트 리스너 추가
 
        // 패널 열고 닫기
        binding.btnToggle.setOnClickListener {
            val state = slidePanel.panelState
            // 닫힌 상태일 경우 열기
            if (state == SlidingUpPanelLayout.PanelState.COLLAPSED) {
                slidePanel.panelState = SlidingUpPanelLayout.PanelState.ANCHORED
            }
            // 열린 상태일 경우 닫기
            else if (state == SlidingUpPanelLayout.PanelState.EXPANDED) {
                slidePanel.panelState = SlidingUpPanelLayout.PanelState.COLLAPSED
            }
        }
 
        // 터치로 슬라이드 가능 여부 설정 (panelState 변경으로 여닫는 건 가능)
        binding.btnTouch.setOnClickListener {
            val touchEnabled = slidePanel.isTouchEnabled
            if (touchEnabled) {
                binding.btnTouch.text = "잠금해제"
                slidePanel.isTouchEnabled = false
            } else {
                binding.btnTouch.text = "터치잠금"
                slidePanel.isTouchEnabled = true
            }
        }
 
        // 패널 활성화 여부 설정 (터치, 함수 모두 불가능)
        binding.btnEnable.setOnClickListener {
            val enabled = slidePanel.isEnabled
            if (enabled) {
                binding.btnEnable.text = "활성화"
                slidePanel.isEnabled = false
            } else {
                binding.btnEnable.text = "비활성화"
                slidePanel.isEnabled = true
            }
        }
 
    }
 
    // 이벤트 리스너
    inner class PanelEventListener : SlidingUpPanelLayout.PanelSlideListener {
        // 패널이 슬라이드 중일 때
        override fun onPanelSlide(panel: View?, slideOffset: Float) {
            binding.tvSlideOffset.text = slideOffset.toString()
        }
 
        // 패널의 상태가 변했을 때
        override fun onPanelStateChanged(panel: View?, previousState: SlidingUpPanelLayout.PanelState?, newState: SlidingUpPanelLayout.PanelState?) {
            if (newState == SlidingUpPanelLayout.PanelState.COLLAPSED) {
                binding.btnToggle.text = "열기"
            } else if (newState == SlidingUpPanelLayout.PanelState.EXPANDED) {
                binding.btnToggle.text = "닫기"
            }
        }
    }
}

 

메인 액티비티 코드가 오르가 났다면 뷰 바인딩 설정을 해줘야 해요.

 

build.gradle

 buildTypes {
       ...

        buildFeatures {
            viewBinding true
        }
    }

 

https://stickode.com/

 

STICKODE - 스틱코드

스틱코드에서 개발에 필요한 모든 코드를 쉽게 사용하세요

stickode.com