Quellcode durchsuchen

[优化] 优化了正文搜索的界面 #549

HapeLee vor 9 Monaten
Ursprung
Commit
126024feaf

+ 45 - 32
app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentScreen.kt

@@ -19,12 +19,13 @@ import androidx.compose.foundation.lazy.itemsIndexed
 import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.automirrored.filled.ArrowBack
+import androidx.compose.material.icons.filled.Code
+import androidx.compose.material.icons.filled.FindReplace
 import androidx.compose.material.icons.filled.Stop
 import androidx.compose.material3.Card
 import androidx.compose.material3.CardDefaults
 import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
-import androidx.compose.material3.FilterChip
 import androidx.compose.material3.FloatingActionButton
 import androidx.compose.material3.HorizontalDivider
 import androidx.compose.material3.Icon
@@ -52,12 +53,14 @@ import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.toArgb
 import androidx.compose.ui.input.nestedscroll.nestedScroll
+import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.text.buildAnnotatedString
 import androidx.compose.ui.unit.dp
 import io.legado.app.ui.widget.components.AnimatedText
 import io.legado.app.ui.widget.components.EmptyMessageView
 import io.legado.app.ui.widget.components.SearchBarSection
 import io.legado.app.ui.widget.components.TextCard
+import io.legado.app.ui.widget.components.button.AnimatedActionButton
 import io.legado.app.ui.widget.components.lazylist.FastScrollLazyColumn
 import org.koin.androidx.compose.koinViewModel
 
@@ -70,6 +73,7 @@ fun SearchContentScreen(
     viewModel: SearchContentViewModel = koinViewModel()
 ) {
     val activity = LocalActivity.current
+    val context = LocalContext.current
 
     val uiState by viewModel.uiState.collectAsState()
 
@@ -142,7 +146,46 @@ fun SearchContentScreen(
                             Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back")
                         }
                     },
-                    scrollBehavior = scrollBehavior
+                    actions = {
+                        Row(
+                            modifier = Modifier.padding(end = 16.dp),
+                            horizontalArrangement = Arrangement.spacedBy(4.dp)
+                        ) {
+                            AnimatedActionButton(
+                                checked = replaceEnabled,
+                                onCheckedChange = {
+                                    replaceEnabled = it
+                                    if (searchQuery.isNotBlank()) {
+                                        viewModel.startSearch(
+                                            searchQuery,
+                                            replaceEnabled,
+                                            regexReplace
+                                        )
+                                    }
+                                },
+                                icon = Icons.Default.FindReplace,
+                                activeText = "替换开启",
+                                inactiveText = "替换关闭"
+                            )
+
+                            AnimatedActionButton(
+                                checked = regexReplace,
+                                onCheckedChange = {
+                                    regexReplace = it
+                                    if (searchQuery.isNotBlank()) {
+                                        viewModel.startSearch(
+                                            searchQuery,
+                                            replaceEnabled,
+                                            regexReplace
+                                        )
+                                    }
+                                },
+                                icon = Icons.Default.Code,
+                                activeText = "正则开启",
+                                inactiveText = "正则关闭"
+                            )
+                        }
+                    }
                 )
                 SearchBarSection(
                     query = searchQuery,
@@ -151,36 +194,6 @@ fun SearchContentScreen(
                         viewModel.startSearch(searchQuery, replaceEnabled, regexReplace)
                     }
                 )
-                AnimatedVisibility(visible = scrollBehavior.state.heightOffset == 0f) {
-                    Row(
-                        modifier = Modifier
-                            .fillMaxWidth()
-                            .padding(horizontal = 16.dp, vertical = 8.dp),
-                        horizontalArrangement = Arrangement.spacedBy(8.dp),
-                        verticalAlignment = Alignment.CenterVertically
-                    ) {
-                        FilterChip(
-                            selected = replaceEnabled,
-                            onClick = {
-                                replaceEnabled = !replaceEnabled
-                                if (searchQuery.isNotBlank()) {
-                                    viewModel.startSearch(searchQuery, replaceEnabled, regexReplace)
-                                }
-                            },
-                            label = { Text("启用替换") }
-                        )
-                        FilterChip(
-                            selected = regexReplace,
-                            onClick = {
-                                regexReplace = !regexReplace
-                                if (searchQuery.isNotBlank()) {
-                                    viewModel.startSearch(searchQuery, replaceEnabled, regexReplace)
-                                }
-                            },
-                            label = { Text("正则匹配") }
-                        )
-                    }
-                }
                 AnimatedVisibility(visible = contentState == SearchContentState.Loading) {
                     LinearProgressIndicator(
                         modifier = Modifier.fillMaxWidth()

+ 74 - 0
app/src/main/java/io/legado/app/ui/widget/components/button/AnimatedActionButton.kt

@@ -0,0 +1,74 @@
+package io.legado.app.ui.widget.components.button
+
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.material3.ToggleButton
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.unit.dp
+import kotlinx.coroutines.delay
+
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
+@Composable
+fun AnimatedActionButton(
+    checked: Boolean,
+    onCheckedChange: (Boolean) -> Unit,
+    icon: ImageVector,
+    activeText: String,
+    inactiveText: String
+) {
+
+    var showText by remember { mutableStateOf(false) }
+    LaunchedEffect(showText) {
+        if (showText) {
+            delay(1000)
+            showText = false
+        }
+    }
+
+    ToggleButton(
+        contentPadding = PaddingValues(4.dp),
+        checked = checked,
+        onCheckedChange = {
+            onCheckedChange(it)
+            showText = true
+        }
+    ) {
+        Row(
+            verticalAlignment = Alignment.CenterVertically,
+            horizontalArrangement = Arrangement.Center,
+            modifier = Modifier.padding(horizontal = 4.dp)
+        ) {
+            Icon(
+                imageVector = icon,
+                contentDescription = null
+            )
+
+            AnimatedVisibility(
+                visible = showText
+            ) {
+                Text(
+                    text = if (checked) activeText else inactiveText,
+                    style = MaterialTheme.typography.labelMedium,
+                    modifier = Modifier.padding(start = 8.dp),
+                    maxLines = 1,
+                    softWrap = false
+                )
+            }
+        }
+    }
+}