Skip to content

Instantly share code, notes, and snippets.

@fiskurgit
Last active Mar 13, 2019
Embed
What would you like to do?
import android.app.Activity
import android.app.Dialog
import android.content.DialogInterface
import android.graphics.Color
import android.graphics.Point
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.GradientDrawable
import android.os.Build
import android.support.design.widget.BottomSheetBehavior
import android.support.design.widget.CoordinatorLayout
import android.util.DisplayMetrics
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
class FiskDialog(context: Activity, layout: Int, theme: Int) {
val dialog: Dialog
val contentView: View
private var cancelable = true
val coordinatorLayout: CoordinatorLayout
init {
dialog = Dialog(context, theme)
val window = dialog.window
if (window != null) {
window.setDimAmount(0f)
window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
}
contentView = context.layoutInflater.inflate(layout, null)
//Curved top corners:
val curvedBackground = GradientDrawable()
curvedBackground.setColor(Color.WHITE)
val cornerRadius = 8 * (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
curvedBackground.cornerRadii = floatArrayOf(cornerRadius, cornerRadius, cornerRadius, cornerRadius, 0f, 0f, 0f, 0f)
contentView.background = curvedBackground
//Full screen coordinator to hold the bottomsheet
coordinatorLayout = CoordinatorLayout(context)
val layoutParams = WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT)
layoutParams.gravity = Gravity.CENTER
coordinatorLayout.layoutParams = layoutParams
coordinatorLayout.setBackgroundColor(Color.parseColor("#00000000"))
val bottomSheetBehavior = BottomSheetBehavior<View>()
bottomSheetBehavior.skipCollapsed = true
bottomSheetBehavior.isHideable = true
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
val params = CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.MATCH_PARENT, CoordinatorLayout.LayoutParams.WRAP_CONTENT)
params.behavior = bottomSheetBehavior
contentView.layoutParams = params
coordinatorLayout.addView(contentView)
//Any click on the dimmed coordinator in the background should dismiss the dialog (unless setCanceleable(false); has been called):
coordinatorLayout.setOnClickListener { _view -> if (cancelable) BottomSheetBehavior.from(contentView).state = BottomSheetBehavior.STATE_HIDDEN }
bottomSheetBehavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
when (newState) {
BottomSheetBehavior.STATE_HIDDEN -> {
dialog.dismiss()
//todo - create dismiss listener interface
}
}
}
//slideOffset is float in range 0 to 1 - remapped to 0 to 153 (0x99000000)
override fun onSlide(bottomSheet: View, slideOffset: Float) {
val alpha = map(slideOffset, 0f, 1f, 0f, 153f).toInt()
val overlayColor = Color.argb(alpha, Color.red(Color.BLACK), Color.green(Color.BLACK), Color.blue(Color.BLACK))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && window != null) {
window.statusBarColor = overlayColor
}
coordinatorLayout.setBackgroundColor(overlayColor)
}
})
dialog.setContentView(coordinatorLayout)
//Without this the bottom sheet doesn't animate, despite the default state being hidden
BottomSheetBehavior.from(contentView).state = BottomSheetBehavior.STATE_HIDDEN
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) dialog.create()
}
fun show() {
dialog.show()
contentView.post { BottomSheetBehavior.from(contentView).setState(BottomSheetBehavior.STATE_EXPANDED) }
}
fun dismiss() {
BottomSheetBehavior.from(contentView).state = BottomSheetBehavior.STATE_HIDDEN
}
fun setOnShowListener(onShowListener: DialogInterface.OnShowListener) {
dialog.setOnShowListener(onShowListener)
}
fun setCancelable(cancelable: Boolean) {
this.cancelable = cancelable
dialog.setCancelable(cancelable)
}
private fun map(value: Float, start1: Float, stop1: Float, start2: Float, stop2: Float): Float {
return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1))
}
fun setMaxWidth(dp: Float) {
val maxWidth = Math.round(contentView.context.resources.displayMetrics.density * dp)
val display = dialog.window!!.windowManager.defaultDisplay
val size = Point()
display.getSize(size)
if (size.x > maxWidth) {
contentView.layoutParams.width = maxWidth
(contentView.layoutParams as CoordinatorLayout.LayoutParams).gravity = Gravity.CENTER_HORIZONTAL
}
}
fun setMaxWidth(dimenRes: Int) {
val dp = contentView.context.resources.getDimension(dimenRes)
setMaxWidth(dp)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment