Last active
March 29, 2019 08:42
-
-
Save premacck/d3bcf4f8061a3156c8e08310f628a090 to your computer and use it in GitHub Desktop.
AlertDialog like DoalogFragment with blur background. Works with BlurKit (https://github.com/CameraKit/blurkit-android) and Anko (https://github.com/Kotlin/anko)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// TODO: add package info here | |
import android.annotation.SuppressLint | |
import android.os.Bundle | |
import android.view.LayoutInflater | |
import android.view.View | |
import android.view.ViewGroup | |
import android.view.accessibility.AccessibilityNodeInfo | |
import androidx.annotation.StringRes | |
import androidx.annotation.StyleRes | |
import androidx.appcompat.app.AppCompatActivity | |
import androidx.cardview.widget.CardView | |
import androidx.coordinatorlayout.widget.CoordinatorLayout | |
import androidx.core.view.AccessibilityDelegateCompat | |
import androidx.core.view.ViewCompat | |
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat | |
import androidx.fragment.app.DialogFragment | |
import io.alterac.blurkit.BlurLayout | |
import kotlinx.android.synthetic.main.design_blur_alert_dialog.* | |
import org.jetbrains.anko.find | |
import org.jetbrains.anko.sdk27.coroutines.onClick | |
/** | |
* Prem's creation, on 18/03/19 | |
*/ | |
class BlurAlertDialog : DialogFragment() { | |
private lateinit var alertDialog: CardView | |
private lateinit var blurLayout: BlurLayout | |
var isHideable: Boolean = true | |
@StyleRes | |
var styleRes: Int = -1 | |
@StringRes | |
var title: String? = null | |
@StringRes | |
var message: String? = null | |
@StringRes | |
var positiveText: Int = -1 | |
@StringRes | |
var negativeText: Int = -1 | |
private var positiveClickListener: OnClickListener? = null | |
private var negativeClickListener: OnClickListener? = null | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setStyle(DialogFragment.STYLE_NORMAL, styleRes) | |
} | |
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = | |
wrapInBottomSheet() | |
override fun onStart() { | |
super.onStart() | |
blurLayout.beginBlur() | |
validateAndAddLayout() | |
setListeners() | |
} | |
override fun onStop() { | |
blurLayout.pauseBlur() | |
super.onStop() | |
} | |
override fun dismiss() { | |
alertDialog.zoomOut()?.then { super.dismiss() } | |
} | |
private fun initWith(builder: Builder) { | |
this.styleRes = builder.styleRes | |
this.title = builder.title | |
this.message = builder.message | |
this.positiveText = builder.positiveText | |
this.negativeText = builder.negativeText | |
this.positiveClickListener = builder.positiveClickListener | |
this.negativeClickListener = builder.negativeClickListener | |
} | |
private fun wrapInBottomSheet(): View? { | |
val rootLayout = View.inflate(context, R.layout.design_blur_alert_dialog, null) | |
val coordinatorLayout = rootLayout.find<CoordinatorLayout>(R.id.coordinator) | |
blurLayout = coordinatorLayout.find(R.id.touch_outside_blur_layout) | |
alertDialog = coordinatorLayout.find(R.id.alert_dialog) | |
alertDialog.zoomIn() | |
return rootLayout | |
} | |
private fun validateAndAddLayout() { | |
title_text.text = title | |
message_text.text = message | |
if (positiveText != -1) { | |
positive_btn.makeVisible() | |
positive_btn.setText(positiveText) | |
positive_btn.onClick { positiveClickListener?.onClick(this@BlurAlertDialog) } | |
} else { | |
positive_btn.makeGone() | |
} | |
if (negativeText != -1) { | |
negative_btn.makeVisible() | |
negative_btn.setText(negativeText) | |
negative_btn.onClick { negativeClickListener?.onClick(this@BlurAlertDialog) } | |
} else { | |
negative_btn.makeGone() | |
} | |
} | |
override fun getTheme(): Int = styleRes | |
@SuppressLint("ClickableViewAccessibility") | |
private fun setListeners() { | |
blurLayout.onClick { | |
if (isAdded && isHideable) { | |
dismiss() | |
} | |
} | |
ViewCompat.setAccessibilityDelegate(alertDialog, object : AccessibilityDelegateCompat() { | |
override fun onInitializeAccessibilityNodeInfo(host: View?, info: AccessibilityNodeInfoCompat?) { | |
super.onInitializeAccessibilityNodeInfo(host, info) | |
if (isHideable) { | |
info?.addAction(AccessibilityNodeInfo.ACTION_DISMISS) | |
info?.isDismissable = true | |
} else { | |
info?.isDismissable = false | |
} | |
} | |
override fun performAccessibilityAction(host: View?, action: Int, args: Bundle?): Boolean { | |
return if (action == AccessibilityNodeInfo.ACTION_DISMISS && isHideable) { | |
dismiss() | |
true | |
} else super.performAccessibilityAction(host, action, args) | |
} | |
}) | |
alertDialog.setOnTouchListener { _, _ -> true } | |
} | |
class Builder(private val activity: AppCompatActivity) { | |
@StyleRes | |
var styleRes: Int = R.style.BlurDialog | |
@StringRes | |
var title: String? = null | |
@StringRes | |
var message: String? = null | |
@StringRes | |
var positiveText: Int = -1 | |
@StringRes | |
var negativeText: Int = -1 | |
var positiveClickListener: OnClickListener? = null | |
var negativeClickListener: OnClickListener? = null | |
fun setStyle(@StyleRes styleRes: Int) = apply { this.styleRes = styleRes } | |
fun setTitle(@StringRes title: Int) = apply { this.title = activity.getString(title) } | |
fun setMessage(@StringRes message: Int) = apply { this.message = activity.getString(message) } | |
fun setTitle(title: String?) = apply { this.title = title } | |
fun setMessage(message: String?) = apply { this.message = message } | |
fun setPositiveButton(@StringRes positiveText: Int, onClickListener: (BlurAlertDialog) -> Unit) = apply { | |
positiveText(positiveText) | |
positiveClickListener(object : BlurAlertDialog.OnClickListener { | |
override fun onClick(dialog: BlurAlertDialog) { | |
onClickListener(dialog) | |
} | |
}) | |
} | |
fun setNegativeButton(@StringRes negativeText: Int, onClickListener: (BlurAlertDialog) -> Unit) = apply { | |
negativeText(negativeText) | |
negativeClickListener(object : BlurAlertDialog.OnClickListener { | |
override fun onClick(dialog: BlurAlertDialog) { | |
onClickListener(dialog) | |
} | |
}) | |
} | |
private fun positiveText(@StringRes positiveText: Int) { | |
this.positiveText = positiveText | |
} | |
private fun negativeText(@StringRes negativeText: Int) { | |
this.negativeText = negativeText | |
} | |
private fun positiveClickListener(positiveClickListener: OnClickListener) { | |
this.positiveClickListener = positiveClickListener | |
} | |
private fun negativeClickListener(negativeClickListener: OnClickListener?) { | |
this.negativeClickListener = negativeClickListener | |
} | |
fun show() { | |
val blurAlertDialog = BlurAlertDialog() | |
blurAlertDialog.initWith(this) | |
blurAlertDialog.show(activity.supportFragmentManager, "$title - $message") | |
} | |
} | |
interface OnClickListener { | |
fun onClick(dialog: BlurAlertDialog) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:app="http://schemas.android.com/apk/res-auto" | |
android:id="@+id/coordinator" | |
style="@style/MatchWidthMatchHeight" | |
android:fitsSystemWindows="true"> | |
<io.alterac.blurkit.BlurLayout | |
android:id="@+id/touch_outside_blur_layout" | |
style="@style/BlurLayoutFullScreen" | |
android:importantForAccessibility="no" | |
android:soundEffectsEnabled="false" /> | |
<View | |
style="@style/MatchWidthMatchHeight" | |
android:background="@color/color_light_black_blur_background" | |
android:importantForAccessibility="no" | |
android:soundEffectsEnabled="false" /> | |
<androidx.cardview.widget.CardView | |
android:id="@+id/alert_dialog" | |
style="@style/DefaultCard.WrapHeight" | |
android:layout_gravity="center" | |
app:cardElevation="@dimen/dimen20dp"> | |
<RelativeLayout | |
style="?attr/bottomSheetStyle" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_gravity="center"> | |
<TextView | |
android:id="@+id/title_text" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_margin="@dimen/dimen16dp" | |
android:textColor="@color/black_text" | |
android:textSize="@dimen/text18sp" | |
android:textStyle="bold" /> | |
<TextView | |
android:id="@+id/message_text" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_below="@+id/title_text" | |
android:layout_marginStart="@dimen/dimen16dp" | |
android:layout_marginEnd="@dimen/dimen16dp" /> | |
<Button | |
android:id="@+id/positive_btn" | |
style="@style/Widget.AppCompat.Button.Borderless" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_below="@+id/message_text" | |
android:layout_alignParentEnd="true" | |
android:layout_marginTop="@dimen/dimen8dp" | |
android:layout_marginEnd="@dimen/dimen16dp" | |
android:text="@string/confirm" | |
android:textColor="@color/pumpkin_orange" /> | |
<Button | |
android:id="@+id/negative_btn" | |
style="@style/Widget.AppCompat.Button.Borderless" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_below="@+id/message_text" | |
android:layout_marginTop="@dimen/dimen8dp" | |
android:layout_marginEnd="@dimen/dimen8dp" | |
android:layout_toStartOf="@+id/positive_btn" | |
android:text="@string/cancel" | |
android:textColor="@color/torch_red" /> | |
</RelativeLayout> | |
</androidx.cardview.widget.CardView> | |
</androidx.coordinatorlayout.widget.CoordinatorLayout> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<style name="MatchWidthMatchHeight"> | |
<item name="android:layout_width">match_parent</item> | |
<item name="android:layout_height">match_parent</item> | |
</style> | |
<style name="BlurLayoutFullScreen"> | |
<item name="android:layout_width">match_parent</item> | |
<item name="android:layout_height">match_parent</item> | |
<item name="android:visibility">invisible</item> | |
<item name="blk_blurRadius">2</item> | |
<item name="blk_downscaleFactor">0.12</item> | |
<item name="blk_fps">0</item> | |
</style> | |
<style name="DefaultCard" parent="CardView.Light"> | |
<item name="cardCornerRadius">@dimen/dimen8dp</item> | |
<item name="cardElevation">4dp</item> | |
<item name="cardUseCompatPadding">true</item> | |
</style> | |
<style name="DefaultCard.WrapHeight"> | |
<item name="android:layout_width">match_parent</item> | |
<item name="android:layout_height">wrap_content</item> | |
<item name="android:layout_marginStart">@dimen/dimen8dp</item> | |
<item name="android:layout_marginEnd">@dimen/dimen8dp</item> | |
</style> | |
<style name="BlurDialog" parent="Theme.AppCompat.Light.Dialog"> | |
<item name="android:windowNoTitle">true</item> | |
<item name="android:windowIsFloating">false</item> | |
<item name="bottomSheetStyle">@style/AppModalStyle</item> | |
<item name="android:windowBackground">@android:color/transparent</item> | |
<item name="android:statusBarColor">@color/colorPrimaryDark</item> | |
</style> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.gdn.offline.events.base.util | |
import android.animation.Animator | |
import android.view.View | |
import android.view.ViewPropertyAnimator | |
import android.view.animation.AccelerateInterpolator | |
import android.view.animation.Animation | |
import android.view.animation.AnimationUtils | |
import androidx.annotation.AnimRes | |
import com.gdn.offline.events.R | |
/** | |
* Prem's creation, on 18/03/19 | |
*/ | |
fun BlurLayout.beginBlur() { | |
postDelayed({ | |
visibility = View.VISIBLE | |
startBlur() | |
}, 150) | |
} | |
fun Animation.then(action: () -> Unit) { | |
setAnimationListener(object : Animation.AnimationListener { | |
override fun onAnimationRepeat(animation: Animation?) {} | |
override fun onAnimationStart(animation: Animation?) {} | |
override fun onAnimationEnd(animation: Animation?) { | |
action() | |
} | |
}) | |
} | |
fun ViewPropertyAnimator.then(action: () -> Unit) { | |
setListener(object : Animator.AnimatorListener { | |
override fun onAnimationRepeat(animation: Animator?) {} | |
override fun onAnimationCancel(animation: Animator?) {} | |
override fun onAnimationStart(animation: Animator?) {} | |
override fun onAnimationEnd(animation: Animator?) { | |
action() | |
} | |
}) | |
} | |
fun View.zoomIn(): Animation? = animate(R.anim.zoom_in) | |
fun View.zoomOut(): ViewPropertyAnimator? { | |
val anim = animate() | |
.scaleX(0f) | |
.scaleY(0f) | |
.alpha(0f) | |
.setInterpolator(AccelerateInterpolator()) | |
.setDuration(150) | |
anim.start() | |
return anim | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<set xmlns:android="http://schemas.android.com/apk/res/android"> | |
<scale | |
android:duration="200" | |
android:fromXScale="0%" | |
android:fromYScale="0%" | |
android:interpolator="@android:anim/decelerate_interpolator" | |
android:pivotX="50%" | |
android:pivotY="50%" | |
android:toXScale="102%" | |
android:toYScale="102%" /> | |
<scale | |
android:duration="100" | |
android:fromXScale="102%" | |
android:fromYScale="102%" | |
android:interpolator="@android:anim/decelerate_interpolator" | |
android:pivotX="50%" | |
android:pivotY="50%" | |
android:startOffset="200" | |
android:toXScale="98%" | |
android:toYScale="98%" /> | |
<scale | |
android:duration="150" | |
android:fromXScale="98%" | |
android:fromYScale="98%" | |
android:interpolator="@android:anim/decelerate_interpolator" | |
android:pivotX="50%" | |
android:pivotY="50%" | |
android:startOffset="300" | |
android:toXScale="100%" | |
android:toYScale="100%" /> | |
<alpha | |
android:duration="50" | |
android:fromAlpha="0" | |
android:startOffset="100" | |
android:toAlpha="1" /> | |
</set> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment