Last active
June 6, 2023 06:55
-
-
Save premacck/add41c3b43e7053a017b0a74a05014e0 to your computer and use it in GitHub Desktop.
Bottom sheet dialog with dim and blur background, and curved corners. 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
<?xml version="1.0" encoding="utf-8"?> | |
<shape xmlns:android="http://schemas.android.com/apk/res/android" | |
android:shape="rectangle"> | |
<solid android:color="@color/color_white_ffffff" /> | |
<corners | |
android:topLeftRadius="@dimen/dimen16dp" | |
android:topRightRadius="@dimen/dimen16dp" /> | |
</shape> |
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"?> | |
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:app="http://schemas.android.com/apk/res-auto" | |
android:id="@+id/container" | |
style="@style/MatchWidthMatchHeight" | |
android:fitsSystemWindows="true"> | |
<androidx.coordinatorlayout.widget.CoordinatorLayout | |
android:id="@+id/coordinator" | |
style="@style/MatchWidthMatchHeight" | |
android:elevation="1dp" | |
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" | |
android:importantForAccessibility="no" | |
android:soundEffectsEnabled="false" /> | |
<FrameLayout | |
android:id="@+id/bottom_sheet" | |
style="?attr/bottomSheetStyle" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_gravity="center_horizontal|top" | |
android:elevation="@dimen/dimen50dp" | |
app:layout_behavior="@string/bottom_sheet_behavior" /> | |
</androidx.coordinatorlayout.widget.CoordinatorLayout> | |
</FrameLayout> |
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.os.Bundle | |
import android.annotation.SuppressLint | |
import android.view.LayoutInflater | |
import android.view.View | |
import android.view.ViewGroup | |
import android.view.accessibility.AccessibilityNodeInfo | |
import android.widget.FrameLayout | |
import androidx.annotation.LayoutRes | |
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 androidx.fragment.app.FragmentManager | |
import com.gdn.offline.events.R | |
import com.gdn.offline.events.base.util.animate | |
import com.gdn.offline.events.base.util.beginBlur | |
import com.gdn.offline.events.base.util.then | |
import com.google.android.material.bottomsheet.BottomSheetBehavior | |
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN | |
import io.alterac.blurkit.BlurLayout | |
import org.jetbrains.anko.find | |
import org.jetbrains.anko.sdk27.coroutines.onClick | |
/** | |
* Prem's creation, on 18/03/19 | |
*/ | |
abstract class BlurBottomSheet : DialogFragment() { | |
@Suppress("PropertyName") | |
abstract val TAG: String | |
private lateinit var bottomSheet: FrameLayout | |
private lateinit var blurLayout: BlurLayout | |
private lateinit var behavior: BottomSheetBehavior<FrameLayout> | |
var isHideable: Boolean = true | |
var backStackId: Int = -1 | |
private val bottomSheetCallback = object : BottomSheetBehavior.BottomSheetCallback() { | |
override fun onStateChanged(bottomSheet: View, newState: Int) { | |
if (newState == STATE_HIDDEN) { | |
dismiss() | |
} | |
} | |
override fun onSlide(bottomSheet: View, slideOffset: Float) {} | |
} | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setStyle(DialogFragment.STYLE_NORMAL, R.style.BlurBottomSheetDialog) | |
} | |
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = | |
wrapInBottomSheet() | |
override fun onStart() { | |
super.onStart() | |
blurLayout.beginBlur() | |
if (behavior.state == BottomSheetBehavior.STATE_HIDDEN) { | |
behavior.state = BottomSheetBehavior.STATE_COLLAPSED | |
} | |
} | |
override fun onStop() { | |
blurLayout.pauseBlur() | |
super.onStop() | |
} | |
override fun dismiss() { | |
bottomSheet.animate(R.anim.float_down)?.then { super.dismiss() } | |
} | |
private fun wrapInBottomSheet(): View? { | |
val rootLayout = View.inflate(context, R.layout.design_bottom_sheet_dialog, null) | |
val coordinatorLayout = rootLayout.find<CoordinatorLayout>(R.id.coordinator) | |
blurLayout = coordinatorLayout.find(R.id.touch_outside_blur_layout) | |
bottomSheet = coordinatorLayout.find(R.id.bottom_sheet) | |
bottomSheet.setBackgroundResource(R.drawable.background_bottom_sheet_white) | |
behavior = BottomSheetBehavior.from(bottomSheet).apply { | |
setBottomSheetCallback(bottomSheetCallback) | |
isHideable = isHideable | |
} | |
val bottomSheetView = layoutInflater.inflate(bottomSheetLayout(), coordinatorLayout, false) | |
if (layoutParams() == null) | |
bottomSheet.addView(bottomSheetView) | |
else | |
bottomSheet.addView(bottomSheetView, layoutParams()) | |
setListeners() | |
startAnimations(bottomSheet) | |
return rootLayout | |
} | |
private fun startAnimations(bottomSheet: FrameLayout) { | |
bottomSheet.animate(R.anim.float_up) | |
} | |
override fun getTheme(): Int = R.style.BlurBottomSheetDialog | |
@SuppressLint("ClickableViewAccessibility") | |
private fun setListeners() { | |
blurLayout.onClick { | |
if (isAdded && isHideable) { | |
dismiss() | |
} | |
} | |
ViewCompat.setAccessibilityDelegate(bottomSheet, 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) | |
} | |
}) | |
bottomSheet.setOnTouchListener { _, _ -> true } | |
} | |
fun setIsHideable(cancelable: Boolean) { | |
super.setCancelable(cancelable) | |
if (isHideable != cancelable) { | |
isHideable = cancelable | |
behavior.isHideable = cancelable | |
} | |
} | |
fun show(fragmentManager: FragmentManager) { | |
backStackId = fragmentManager.beginTransaction() | |
.add(this, TAG) | |
.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out) | |
.commit() | |
} | |
@LayoutRes | |
abstract fun bottomSheetLayout(): Int | |
open fun layoutParams(): ViewGroup.LayoutParams? = null | |
} |
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
<color name="color_light_black">#99000000</color> |
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 for the "touch_outside_blur_layout" layout in "design_bottom_sheet_dialog--> | |
<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 for BlurBottomSheet--> | |
<style name="BlurBottomSheetDialog" 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> | |
<style name="AppModalStyle" parent="Widget.Design.BottomSheet.Modal"> | |
<item name="android:background">@drawable/background_bottom_sheet_white</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
import android.view.View | |
import android.view.animation.Animation | |
import android.view.animation.AnimationUtils | |
import androidx.annotation.AnimRes | |
import androidx.appcompat.app.AppCompatActivity | |
import com.gdn.offline.events.base.compoundViews.BlurBottomSheet | |
/** | |
* Prem's creation, on 18/03/19 | |
*/ | |
fun View.animate(@AnimRes animResId: Int): Animation? { | |
clearAnimation() | |
val animation = AnimationUtils.loadAnimation(context, animResId) | |
startAnimation(animation) | |
return animation | |
} | |
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() | |
} | |
}) | |
} | |
// Extension function for delayed blur of the BlurLayout | |
fun BlurLayout.beginBlur() { | |
postDelayed({ | |
visibility = View.VISIBLE | |
startBlur() | |
}, 150) | |
} | |
fun AppCompatActivity.showBottomSheet(bottomSheet: BlurBottomSheet) { | |
bottomSheet.show(supportFragmentManager) | |
} | |
fun BlurBottomSheet.showBottomSheet(bottomSheet: BlurBottomSheet, dismissCurrent: Boolean = true) { | |
if (dismissCurrent) dismiss() | |
bottomSheet.show(activity!!.supportFragmentManager) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can you please share the "float_up" and "float_down" anim files? Furthermore, could you provide an explanation of how to integrate the bottom sheet into this code?