BasicBottomSheet: init

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
Harsh Shandilya 2020-09-19 17:19:30 +05:30
parent afbe29e7da
commit 5d5a068591
No known key found for this signature in database
GPG key ID: 366D7BBAD1031E80
2 changed files with 206 additions and 0 deletions

View file

@ -0,0 +1,145 @@
/*
* Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
* SPDX-License-Identifier: GPL-3.0-only
*/
package com.zeapo.pwdstore.ui.dialogs
import android.content.Context
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.FrameLayout
import androidx.annotation.StringRes
import androidx.core.view.isVisible
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.zeapo.pwdstore.R
import com.zeapo.pwdstore.databinding.BasicBottomSheetBinding
import com.zeapo.pwdstore.utils.resolveAttribute
import com.zeapo.pwdstore.utils.viewBinding
/**
* [BottomSheetDialogFragment] that exposes a simple [androidx.appcompat.app.AlertDialog] like
* API through [Builder] to create a similar UI, just at the bottom of the screen.
*/
class BasicBottomSheet private constructor(
val title: String,
val message: String,
val positiveButtonClickListener: View.OnClickListener?,
val negativeButtonClickListener: View.OnClickListener?,
) : BottomSheetDialogFragment() {
private val binding by viewBinding(BasicBottomSheetBinding::bind)
private var behavior: BottomSheetBehavior<FrameLayout>? = null
private val bottomSheetCallback = object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, slideOffset: Float) {
}
override fun onStateChanged(bottomSheet: View, newState: Int) {
if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
dismiss()
}
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
if (savedInstanceState != null) dismiss()
return layoutInflater.inflate(R.layout.basic_bottom_sheet, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
view.viewTreeObserver.removeOnGlobalLayoutListener(this)
val dialog = dialog as BottomSheetDialog? ?: return
behavior = dialog.behavior
behavior?.apply {
state = BottomSheetBehavior.STATE_EXPANDED
peekHeight = 0
addBottomSheetCallback(bottomSheetCallback)
}
binding.bottomSheetTitle.text = title
binding.bottomSheetMessage.text = message
if (positiveButtonClickListener != null) {
binding.bottomSheetOkButton.isVisible = true
binding.bottomSheetOkButton.setOnClickListener {
positiveButtonClickListener.onClick(it)
dismiss()
}
}
if (negativeButtonClickListener != null) {
binding.bottomSheetCancelButton.isVisible = true
binding.bottomSheetCancelButton.setOnClickListener {
negativeButtonClickListener.onClick(it)
dismiss()
}
}
}
})
val gradientDrawable = GradientDrawable().apply {
setColor(requireContext().resolveAttribute(android.R.attr.windowBackground))
}
view.background = gradientDrawable
}
override fun dismiss() {
super.dismiss()
behavior?.removeBottomSheetCallback(bottomSheetCallback)
}
class Builder(val context: Context) {
private var title: String? = null
private var message: String? = null
private var positiveButtonClickListener: View.OnClickListener? = null
private var negativeButtonClickListener: View.OnClickListener? = null
fun setTitleRes(@StringRes titleRes: Int): Builder {
this.title = context.resources.getString(titleRes)
return this
}
fun setTitle(title: String): Builder {
this.title = title
return this
}
fun setMessageRes(@StringRes messageRes: Int): Builder {
this.message = context.resources.getString(messageRes)
return this
}
fun setMessage(message: String): Builder {
this.message = message
return this
}
fun setPositiveButtonClickListener(listener: View.OnClickListener): Builder {
this.positiveButtonClickListener = listener
return this
}
fun setNegativeButtonClickListener(listener: View.OnClickListener): Builder {
this.negativeButtonClickListener = listener
return this
}
fun build(): BasicBottomSheet {
require(title != null) { "Title needs to be set" }
require(message != null) { "Message needs to be set" }
return BasicBottomSheet(
title!!,
message!!,
positiveButtonClickListener,
negativeButtonClickListener
)
}
}
}

View file

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
~ SPDX-License-Identifier: GPL-3.0-only
-->
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:paddingBottom="24dp">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/bottom_sheet_title"
style="@style/TextAppearance.MaterialComponents.Headline6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Bottom sheet title" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/bottom_sheet_message"
style="@style/TextAppearance.MaterialComponents.Body1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
app:layout_constraintTop_toBottomOf="@id/bottom_sheet_title"
tools:text="A long body of text that serves as the bottom sheet message" />
<com.google.android.material.button.MaterialButton
android:id="@+id/bottom_sheet_cancel_button"
style="@style/AppTheme.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="8dp"
android:text="@string/dialog_cancel"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/bottom_sheet_message"
tools:visibility="visible" />
<com.google.android.material.button.MaterialButton
android:id="@+id/bottom_sheet_ok_button"
style="@style/AppTheme.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="8dp"
android:text="@string/dialog_ok"
android:visibility="gone"
app:layout_constraintEnd_toStartOf="@id/bottom_sheet_cancel_button"
app:layout_constraintTop_toBottomOf="@id/bottom_sheet_message"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>