SlidingUpPanel은 복잡한 설정 없이 위, 아래에서 드래그가 가능한 레이아웃을 구성할 수 있는 라이브러리다.
github.com/hannesa2/AndroidSlidingUpPanel
hannesa2/AndroidSlidingUpPanel
It provides a simple way to add a draggable sliding up panel (popularized by Google Music and Google Maps) - hannesa2/AndroidSlidingUpPanel
github.com
Gradle에 라이브러리 추가
프로젝트, 앱 Gradle에 다음 문장을 추가한다.
allprojects { repositories { ... maven { url 'https://jitpack.io' } } }
dependencies { ... implementation 'com.github.hannesa2:AndroidSlidingUpPanel:4.2.1' }
SlidingUpPanel 사용하기
SlidingUpPanel을 사용하려면 최상단의 레이아웃을 다음으로 바꿔야한다.
com.sothree.slidinguppanel.SlidingUpPanelLayout
SlidingUpPanelLayout은 반드시 두 개의 자녀 뷰를 가지고 있어야 하며, 배경으로 사용될 뷰가 먼저 오게하고, 슬라이드 할 뷰가 뒤에 오게 정렬한다.

SlidingUpPanelLayout에 몇 가지 옵션을 정할 수 있다. gravity는 반드시 정해줘야 한다.
<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"> </com.sothree.slidinguppanel.SlidingUpPanelLayout>
android:gravity: 어느 방향에서 드래그 할 것인지 설정 (top, bottom) 필수
app:umanoDragView: 드래그 할 때 사용할 뷰 선택 (기본값: 최상위 레이아웃, 위 이미지의 slide_layout)
app:umanoPanelHeight: 닫혀있을 때 보이는 높이 (기본값: 68dp)
app:umanoOverlay: 슬라이드 패널을 오버레이로 만들지 여부 (기본값: false)
- true일 경우 슬라이드 패널의 기본 배경색이 투명해지고, 배경 레이아웃의 높이가 화면 크기로 조정된다.
- false일 경우 슬라이드 패널이 불투명해지고, 배경 레이아웃의 높이가 PanelHeight만큼 줄어든다.
app:umanoFadeColor: 패널이 열려있을 때의 배경 색상 (기본값: 20% 어두워짐)
그 외에 옵션들은 GitHub 페이지에서 확인하길 바란다.
예시 앱
<?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>


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 = "닫기" } } } }
실행 결과

'프로그래밍 > 안드로이드' 카테고리의 다른 글
[Android/KakaoAPI] 커스텀 마커 & 말풍선, 마커 클릭 시 이벤트 (0) | 2021.01.19 |
---|---|
[Android/KakaoAPI] 장소 검색 결과를 리사이클러 뷰에 추가 (0) | 2021.01.14 |
[Android/KakaoAPI] 카카오 장소 검색 (Retrofit) (0) | 2021.01.13 |
[Android/KakaoAPI] 카카오 지도에서 현재 위치 추적 (3) | 2021.01.12 |
[Android/KakaoAPI] 안드로이드 앱에서 카카오 지도 사용하기 (0) | 2021.01.10 |