geekdroid: add ModalBottomSheetActivity a compose based BottomSheetActivity. geekttrss-1.6.7
authorDa Risk <da_risk@geekorum.com>
Thu, 07 Mar 2024 18:45:18 -0400
changeset 70 f6cf2e8bf04d
parent 69 1167496633b2
child 71 0fe2801ff0a2
geekdroid: add ModalBottomSheetActivity a compose based BottomSheetActivity. Deprecate BottomSheetDialogActivity
geekdroid/build.gradle.kts
geekdroid/src/main/java/com/geekorum/geekdroid/app/BottomSheetDialogActivity.kt
geekdroid/src/main/java/com/geekorum/geekdroid/app/ModalBottomSheetActivity.kt
geekdroid/src/main/res/values/styles.xml
gradle/libs.versions.toml
--- a/geekdroid/build.gradle.kts	Thu Mar 07 18:44:25 2024 -0400
+++ b/geekdroid/build.gradle.kts	Thu Mar 07 18:45:18 2024 -0400
@@ -53,8 +53,13 @@
         abortOnError = false
     }
 
-    dataBinding {
-        enable = true
+    buildFeatures {
+        dataBinding = true
+        compose = true
+    }
+
+    composeOptions {
+        kotlinCompilerExtensionVersion = libs.versions.androidx.compose.compiler.get()
     }
 
     packaging {
@@ -106,6 +111,11 @@
     implementation(libs.work.runtime)
     implementation(libs.preference.ktx)
 
+    // compose stuff
+    implementation(platform(libs.androidx.compose.bom))
+    implementation(libs.androidx.compose.material3)
+    implementation(libs.androidx.activity.compose)
+
 }
 
 
--- a/geekdroid/src/main/java/com/geekorum/geekdroid/app/BottomSheetDialogActivity.kt	Thu Mar 07 18:44:25 2024 -0400
+++ b/geekdroid/src/main/java/com/geekorum/geekdroid/app/BottomSheetDialogActivity.kt	Thu Mar 07 18:45:18 2024 -0400
@@ -41,6 +41,7 @@
  * React like a [BottomSheetDialogFragment] but is a separate [Activity].
  * This allows you to launch the bottom sheet easily from another external activity.
  */
+@Deprecated("Use ModalBottomSheetActivity", replaceWith = ReplaceWith("ModalBottomSheetActivity"))
 abstract class BottomSheetDialogActivity : ComponentActivity() {
 
     private lateinit var binding: ActivityBottomSheetDialogBinding
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/geekdroid/src/main/java/com/geekorum/geekdroid/app/ModalBottomSheetActivity.kt	Thu Mar 07 18:45:18 2024 -0400
@@ -0,0 +1,109 @@
+/*
+ * Geekdroid is a utility library for development on the Android
+ * Platform.
+ *
+ * Copyright (C) 2017-2024 by Frederic-Charles Barthelery.
+ *
+ * This file is part of Geekdroid.
+ *
+ * Geekdroid is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Geekdroid is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Geekdroid.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.geekorum.geekdroid.app
+
+import android.app.Activity
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.BackHandler
+import androidx.activity.compose.setContent
+import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ModalBottomSheet
+import androidx.compose.material3.SheetValue
+import androidx.compose.material3.rememberModalBottomSheetState
+import androidx.compose.runtime.*
+import androidx.lifecycle.lifecycleScope
+import com.geekorum.geekdroid.R
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.channels.consumeEach
+import kotlinx.coroutines.launch
+
+/**
+ * React like a [BottomSheetDialogFragment] but is a separate [Activity].
+ * This allows you to launch the bottom sheet easily from another external activity.
+ * This implementation use Compose and Material3 [ModalBottomSheet]
+ *
+ * The activity should use [Theme.Geekdroid.ModalBottomSheetDialogActivity][R.style.Theme_Geekdroid_ModalBottomSheetDialogActivity]
+ * theme or equivalent to work correctly.
+ */
+open class ModalBottomSheetActivity : ComponentActivity() {
+    private var _sheetContent: @Composable ColumnScope.() -> Unit by mutableStateOf({})
+
+    private val dismissEventChannel = Channel<Unit>()
+
+    @OptIn(ExperimentalMaterial3Api::class)
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        setContent {
+            val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
+            val coroutineScope = rememberCoroutineScope()
+
+            LaunchedEffect(Unit) {
+                dismissEventChannel.consumeEach {
+                    sheetState.hide()
+                }
+            }
+
+            BackHandler(sheetState.targetValue != SheetValue.Hidden) {
+                coroutineScope.launch {
+                    sheetState.hide()
+                }
+            }
+
+            // dismiss automatically when hidden
+            var wasShown by remember {  mutableStateOf(false) }
+            LaunchedEffect(sheetState.isVisible) {
+                if (sheetState.isVisible) {
+                    wasShown = true
+                } else if (wasShown) {
+                    finish()
+                }
+            }
+
+
+            ModalBottomSheet(
+                sheetState = sheetState,
+                onDismissRequest = {},
+                dragHandle = null,
+                windowInsets = WindowInsets(0)
+            ) {
+                _sheetContent()
+            }
+        }
+    }
+
+    fun setSheetContent(
+        content: @Composable ColumnScope.() -> Unit
+    ) {
+        _sheetContent = content
+    }
+
+    fun dismiss() {
+        lifecycleScope.launch {
+            dismissEventChannel.send(Unit)
+        }
+    }
+}
--- a/geekdroid/src/main/res/values/styles.xml	Thu Mar 07 18:44:25 2024 -0400
+++ b/geekdroid/src/main/res/values/styles.xml	Thu Mar 07 18:45:18 2024 -0400
@@ -42,4 +42,13 @@
         <item name="android:windowTranslucentStatus">false</item>
     </style>
 
+    <style name="Theme.Geekdroid.ModalBottomSheetDialogActivity" parent="android:Theme.Dialog">
+        <item name="android:windowIsFloating">false</item>
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
+    </style>
+
+
 </resources>
--- a/gradle/libs.versions.toml	Thu Mar 07 18:44:25 2024 -0400
+++ b/gradle/libs.versions.toml	Thu Mar 07 18:45:18 2024 -0400
@@ -1,5 +1,8 @@
 [versions]
 annotation = "1.7.1"
+androidx-activity = "1.8.2"
+androidx-compose-bom = "2024.02.02"
+androidx-compose-compiler = "1.5.9"
 browser = "1.8.0"
 constraintlayout = "2.1.4"
 coordinatorlayout = "1.2.0"
@@ -25,6 +28,12 @@
 
 [libraries]
 annotation = { module = "androidx.annotation:annotation", version.ref = "annotation" }
+
+androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" }
+
+androidx-compose-bom = { module = "androidx.compose:compose-bom", version.ref = "androidx-compose-bom" }
+androidx-compose-material3 = { module = "androidx.compose.material3:material3" }
+
 browser = { module = "androidx.browser:browser", version.ref = "browser" }
 constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" }
 coordinatorlayout = { module = "androidx.coordinatorlayout:coordinatorlayout", version.ref = "coordinatorlayout" }