SlidingUpPanel은 복잡한 설정 없이 위, 아래에서 드래그가 가능한 레이아웃을 구성할 수 있는 라이브러리다.
github.com/hannesa2/AndroidSlidingUpPanel
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 |