HapeLee 10 месяцев назад
Родитель
Сommit
cc61742b5d

+ 2 - 3
app/src/main/java/io/legado/app/ui/about/AboutScreen.kt

@@ -1,7 +1,6 @@
 package io.legado.app.ui.about
 
 import androidx.compose.foundation.Image
-import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
@@ -21,7 +20,7 @@ import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.MaterialTheme.colorScheme
-import androidx.compose.material3.MediumTopAppBar
+import androidx.compose.material3.MediumFlexibleTopAppBar
 import androidx.compose.material3.Scaffold
 import androidx.compose.material3.Text
 import androidx.compose.material3.TopAppBarDefaults
@@ -61,7 +60,7 @@ fun AboutScreen(
     Scaffold(
         modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
         topBar = {
-            MediumTopAppBar(
+            MediumFlexibleTopAppBar(
                 title = { Text(stringResource(R.string.about)) },
                 navigationIcon = {
                     IconButton(onClick = onBack) {

+ 38 - 7
app/src/main/java/io/legado/app/ui/book/bookmark/AllBookmarkScreen.kt

@@ -14,7 +14,15 @@ import androidx.compose.animation.fadeOut
 import androidx.compose.animation.shrinkVertically
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.navigationBarsPadding
+import androidx.compose.foundation.layout.padding
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.automirrored.filled.ArrowBack
 import androidx.compose.material.icons.filled.KeyboardArrowDown
@@ -22,8 +30,32 @@ import androidx.compose.material.icons.filled.MoreVert
 import androidx.compose.material.icons.filled.Search
 import androidx.compose.material.icons.filled.UnfoldLess
 import androidx.compose.material.icons.filled.UnfoldMore
-import androidx.compose.material3.*
-import androidx.compose.runtime.*
+import androidx.compose.material3.AlertDialog
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.DropdownMenu
+import androidx.compose.material3.DropdownMenuItem
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.MediumFlexibleTopAppBar
+import androidx.compose.material3.ModalBottomSheet
+import androidx.compose.material3.OutlinedButton
+import androidx.compose.material3.OutlinedTextField
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextButton
+import androidx.compose.material3.TopAppBarDefaults
+import androidx.compose.material3.rememberModalBottomSheetState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+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.draw.rotate
@@ -35,9 +67,9 @@ import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.dp
 import io.legado.app.data.entities.Bookmark
 import io.legado.app.ui.widget.components.EmptyMessageView
+import io.legado.app.ui.widget.components.SearchBarSection
 import io.legado.app.ui.widget.components.lazylist.FastScrollLazyColumn
 import io.legado.app.ui.widget.components.lazylist.Scroller
-import io.legado.app.ui.widget.components.SearchBarSection
 import org.koin.androidx.compose.koinViewModel
 
 @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class,
@@ -77,11 +109,10 @@ fun AllBookmarkScreen(
         modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
         topBar = {
             Column {
-                MediumTopAppBar(
+                MediumFlexibleTopAppBar(
                     title = {
                         Text(
-                            text = "所有书签",
-                            style = MaterialTheme.typography.titleLarge
+                            text = "所有书签"
                         )
                     },
                     scrollBehavior = scrollBehavior,

+ 5 - 4
app/src/main/java/io/legado/app/ui/book/explore/ExploreShowScreen.kt

@@ -56,7 +56,7 @@ import androidx.compose.material3.FilterChip
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
 import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.MediumTopAppBar
+import androidx.compose.material3.MediumFlexibleTopAppBar
 import androidx.compose.material3.ModalBottomSheet
 import androidx.compose.material3.OutlinedButton
 import androidx.compose.material3.Scaffold
@@ -253,7 +253,8 @@ fun ExploreShowScreen(
                 }
 
                 FlowRow(
-                    modifier = Modifier.fillMaxWidth()
+                    modifier = Modifier
+                        .fillMaxWidth()
                         .padding(16.dp)
                 ) {
                     filteredKinds.forEach { kind ->
@@ -393,7 +394,7 @@ fun KindListItem(
     )
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
 @Composable
 fun ExploreTopBar(
     title: String,
@@ -408,7 +409,7 @@ fun ExploreTopBar(
 ) {
     var showMenu by remember { mutableStateOf(false) }
 
-    MediumTopAppBar(
+    MediumFlexibleTopAppBar(
         title = { AnimatedTextLine(title, maxLines = 1, overflow = TextOverflow.Ellipsis) },
         navigationIcon = {
             IconButton(onClick = onBack) {

+ 2 - 10
app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditScreen.kt

@@ -3,13 +3,11 @@ package io.legado.app.ui.book.info.edit
 import androidx.activity.compose.rememberLauncherForActivityResult
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.heightIn
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.rememberScrollState
@@ -34,15 +32,11 @@ import androidx.compose.material3.FilledTonalIconButton
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
 import androidx.compose.material3.IconButtonDefaults
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.MediumTopAppBar
+import androidx.compose.material3.MediumFlexibleTopAppBar
 import androidx.compose.material3.OutlinedButton
-import androidx.compose.material3.OutlinedIconButton
 import androidx.compose.material3.OutlinedTextField
-import androidx.compose.material3.OutlinedTextFieldDefaults
 import androidx.compose.material3.Scaffold
 import androidx.compose.material3.Text
-import androidx.compose.material3.TextField
 import androidx.compose.material3.TopAppBarDefaults
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
@@ -52,8 +46,6 @@ import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.Modifier.Companion
-import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.input.nestedscroll.nestedScroll
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.stringResource
@@ -79,7 +71,7 @@ fun BookInfoEditScreen(
     Scaffold(
         modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
         topBar = {
-            MediumTopAppBar(
+            MediumFlexibleTopAppBar(
                 title = { Text(text = stringResource(id = R.string.book_info_edit)) },
                 navigationIcon = {
                     IconButton(onClick = onBack) {

+ 22 - 27
app/src/main/java/io/legado/app/ui/book/readRecord/ReadRecordScreen.kt

@@ -28,10 +28,11 @@ import androidx.compose.material.icons.filled.Timeline
 import androidx.compose.material3.Card
 import androidx.compose.material3.CardDefaults
 import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
 import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.MediumTopAppBar
+import androidx.compose.material3.MediumFlexibleTopAppBar
 import androidx.compose.material3.Scaffold
 import androidx.compose.material3.Surface
 import androidx.compose.material3.Text
@@ -70,13 +71,8 @@ import org.koin.androidx.compose.koinViewModel
 import java.time.LocalDate
 import java.time.format.DateTimeFormatter
 import java.util.Date
-import kotlin.collections.component1
-import kotlin.collections.component2
-import kotlin.collections.isNotEmpty
-import kotlin.collections.map
-import kotlin.collections.sumOf
 
-@OptIn(ExperimentalMaterial3Api::class)
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
 @Composable
 fun ReadRecordScreen(
     viewModel: ReadRecordViewModel = koinViewModel(),
@@ -98,7 +94,7 @@ fun ReadRecordScreen(
     }
 
     LaunchedEffect(searchText) {
-        if (showSearch) {
+        if (showSearch && searchText.isNotBlank()) {
             delay(100L)
             viewModel.loadData(searchText)
         }
@@ -108,24 +104,21 @@ fun ReadRecordScreen(
         modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
         topBar = {
             Column {
-                MediumTopAppBar(
+                MediumFlexibleTopAppBar(
                     title = {
-                        val (mainTitle, subTitle) = when (displayMode) {
-                            DisplayMode.AGGREGATE -> "阅读记录" to "汇总视图"
-                            DisplayMode.TIMELINE -> "阅读记录" to "时间线视图"
-                            DisplayMode.LATEST -> "阅读记录" to "最后阅读"
-                        }
-                        Column {
-                            Text(
-                                text = mainTitle,
-                                style = MaterialTheme.typography.titleLarge,
-                            )
-
-                            AnimatedTextLine(
-                                text = subTitle,
-                                style = MaterialTheme.typography.titleMedium
-                            )
+                        Text(
+                            text = "阅读记录"
+                        )
+                    },
+                    subtitle = {
+                        val subTitle = when (displayMode) {
+                            DisplayMode.AGGREGATE -> "汇总视图"
+                            DisplayMode.TIMELINE -> "时间线视图"
+                            DisplayMode.LATEST -> "最后阅读"
                         }
+                        AnimatedTextLine(
+                            text = subTitle
+                        )
                     },
                     navigationIcon = {
                         IconButton(onClick = onBackClick) {
@@ -170,18 +163,20 @@ fun ReadRecordScreen(
                         selectedDate = state.selectedDate,
                         onDateSelected = { date ->
                             viewModel.setSelectedDate(date)
-                            showCalendar = false // 选择后自动收起日历
+                            showCalendar = false
                         },
                         onClearDate = {
                             viewModel.setSelectedDate(null)
-                            showCalendar = false // 清除后自动收起
+                            showCalendar = false
                         }
                     )
                 }
             }
         }
     ) { padding ->
-        Column(modifier = Modifier.padding(padding).fillMaxSize()) {
+        Column(modifier = Modifier
+            .padding(padding)
+            .fillMaxSize()) {
             val contentState = when {
                 state.isLoading -> "LOADING"
                 (displayMode == DisplayMode.AGGREGATE && state.groupedRecords.isEmpty()) ||

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

@@ -31,7 +31,7 @@ import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
 import androidx.compose.material3.LinearProgressIndicator
 import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.MediumTopAppBar
+import androidx.compose.material3.MediumFlexibleTopAppBar
 import androidx.compose.material3.PlainTooltip
 import androidx.compose.material3.Scaffold
 import androidx.compose.material3.Text
@@ -126,7 +126,7 @@ fun SearchContentScreen(
         modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
         topBar = {
             Column {
-                MediumTopAppBar(
+                MediumFlexibleTopAppBar(
                     title = {
                         val title = if (searchQuery.isNotBlank() && searchResults.isNotEmpty()) {
                             "共 ${searchResults.size} 条结果"

+ 4 - 3
app/src/main/java/io/legado/app/ui/main/my/MyScreen.kt

@@ -26,9 +26,10 @@ import androidx.compose.material.icons.filled.Translate
 import androidx.compose.material.icons.filled.Web
 import androidx.compose.material3.DropdownMenuItem
 import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
-import androidx.compose.material3.MediumTopAppBar
+import androidx.compose.material3.MediumFlexibleTopAppBar
 import androidx.compose.material3.Scaffold
 import androidx.compose.material3.Switch
 import androidx.compose.material3.Text
@@ -55,7 +56,7 @@ import io.legado.app.ui.widget.components.SettingItem
 import io.legado.app.ui.widget.components.SplicedColumnGroup
 
 
-@OptIn(ExperimentalMaterial3Api::class)
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
 @Composable
 fun MyScreen(
     viewModel: MyViewModel,
@@ -70,7 +71,7 @@ fun MyScreen(
         contentWindowInsets = WindowInsets.systemBars
             .only(WindowInsetsSides.Horizontal + WindowInsetsSides.Top),
         topBar = {
-            MediumTopAppBar(
+            MediumFlexibleTopAppBar(
                 title = {
                     Text(
                         text = stringResource(R.string.my)

+ 80 - 16
app/src/main/java/io/legado/app/ui/replace/edit/ReplaceEditScreen.kt

@@ -6,16 +6,63 @@ import androidx.compose.animation.slideOutVertically
 import androidx.compose.foundation.background
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.horizontalScroll
-import androidx.compose.foundation.layout.*
 import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.ime
+import androidx.compose.foundation.layout.imePadding
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.automirrored.filled.ArrowBack
 import androidx.compose.material.icons.automirrored.filled.HelpOutline
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material3.*
-import androidx.compose.runtime.*
+import androidx.compose.material.icons.filled.Check
+import androidx.compose.material.icons.filled.MoreVert
+import androidx.compose.material.icons.filled.Save
+import androidx.compose.material.icons.filled.Settings
+import androidx.compose.material3.AlertDialog
+import androidx.compose.material3.AssistChip
+import androidx.compose.material3.BottomAppBar
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.Checkbox
+import androidx.compose.material3.DropdownMenu
+import androidx.compose.material3.DropdownMenuItem
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
+import androidx.compose.material3.ExposedDropdownMenuAnchorType
+import androidx.compose.material3.ExposedDropdownMenuBox
+import androidx.compose.material3.ExposedDropdownMenuDefaults
+import androidx.compose.material3.FilterChip
+import androidx.compose.material3.FilterChipDefaults
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.MediumFlexibleTopAppBar
+import androidx.compose.material3.OutlinedButton
+import androidx.compose.material3.OutlinedTextField
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextButton
+import androidx.compose.material3.TopAppBarDefaults
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.State
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateMapOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberUpdatedState
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clip
@@ -32,7 +79,7 @@ fun keyboardAsState(): State<Boolean> {
     return rememberUpdatedState(isImeVisible)
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
 @Composable
 fun ReplaceEditScreen(
     onBack: () -> Unit,
@@ -48,7 +95,7 @@ fun ReplaceEditScreen(
         Scaffold(
             modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
             topBar = {
-                MediumTopAppBar(
+                MediumFlexibleTopAppBar(
                     title = { Text(if (state.id > 0) "编辑替换规则" else "新增替换规则") },
                     navigationIcon = {
                         IconButton(onClick = onBack) { Icon(Icons.AutoMirrored.Filled.ArrowBack, "Back") }
@@ -111,7 +158,10 @@ fun ReplaceEditScreen(
                     label = { Text("规则名称") },
                     modifier = Modifier
                         .fillMaxWidth()
-                        .onFocusChanged { if (it.isFocused) viewModel.activeField = ReplaceEditViewModel.ActiveField.Name },
+                        .onFocusChanged {
+                            if (it.isFocused) viewModel.activeField =
+                                ReplaceEditViewModel.ActiveField.Name
+                        },
                     singleLine = true
                 )
 
@@ -129,7 +179,10 @@ fun ReplaceEditScreen(
                     placeholder = { Text("输入正则表达式或关键字") },
                     modifier = Modifier
                         .fillMaxWidth()
-                        .onFocusChanged { if (it.isFocused) viewModel.activeField = ReplaceEditViewModel.ActiveField.Pattern }
+                        .onFocusChanged {
+                            if (it.isFocused) viewModel.activeField =
+                                ReplaceEditViewModel.ActiveField.Pattern
+                        }
                 )
 
                 OutlinedTextField(
@@ -139,7 +192,10 @@ fun ReplaceEditScreen(
                     placeholder = { Text("输入替换内容或捕获组") },
                     modifier = Modifier
                         .fillMaxWidth()
-                        .onFocusChanged { if (it.isFocused) viewModel.activeField = ReplaceEditViewModel.ActiveField.Replacement }
+                        .onFocusChanged {
+                            if (it.isFocused) viewModel.activeField =
+                                ReplaceEditViewModel.ActiveField.Replacement
+                        }
                 )
 
                 Row(
@@ -187,7 +243,10 @@ fun ReplaceEditScreen(
                     placeholder = { Text("指定规则适用的范围") },
                     modifier = Modifier
                         .fillMaxWidth()
-                        .onFocusChanged { if (it.isFocused) viewModel.activeField = ReplaceEditViewModel.ActiveField.Scope }
+                        .onFocusChanged {
+                            if (it.isFocused) viewModel.activeField =
+                                ReplaceEditViewModel.ActiveField.Scope
+                        }
                 )
 
                 OutlinedTextField(
@@ -197,7 +256,10 @@ fun ReplaceEditScreen(
                     placeholder = { Text("指定规则不适用的范围") },
                     modifier = Modifier
                         .fillMaxWidth()
-                        .onFocusChanged { if (it.isFocused) viewModel.activeField = ReplaceEditViewModel.ActiveField.Exclude }
+                        .onFocusChanged {
+                            if (it.isFocused) viewModel.activeField =
+                                ReplaceEditViewModel.ActiveField.Exclude
+                        }
                 )
 
                 OutlinedTextField(
@@ -261,13 +323,15 @@ fun GroupSelector(
                 value = currentGroup,
                 onValueChange = onGroupChange,
                 label = { Text("分组") },
-                placeholder = {Text("默认")},
+                placeholder = { Text("默认") },
                 trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
                 colors = ExposedDropdownMenuDefaults.outlinedTextFieldColors(),
-                modifier = Modifier.fillMaxWidth().menuAnchor(
-                    ExposedDropdownMenuAnchorType.PrimaryEditable,
-                    true
-                )
+                modifier = Modifier
+                    .fillMaxWidth()
+                    .menuAnchor(
+                        ExposedDropdownMenuAnchorType.PrimaryEditable,
+                        true
+                    )
             )
             ExposedDropdownMenu(
                 expanded = expanded,

+ 56 - 7
app/src/main/java/io/legado/app/ui/widget/components/SearchBarSection.kt

@@ -1,11 +1,19 @@
 package io.legado.app.ui.widget.components
 
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.animation.scaleIn
+import androidx.compose.animation.scaleOut
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Clear
 import androidx.compose.material.icons.filled.Search
+import androidx.compose.material3.DropdownMenu
 import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
@@ -15,6 +23,11 @@ import androidx.compose.material3.Text
 import androidx.compose.material3.TextField
 import androidx.compose.material3.TextFieldDefaults
 import androidx.compose.runtime.Composable
+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.Color
 import androidx.compose.ui.unit.dp
@@ -25,8 +38,14 @@ fun SearchBarSection(
     query: String,
     onQueryChange: (String) -> Unit,
     placeholder: String = "搜索书名",
-    backgroundColor: Color = MaterialTheme.colorScheme.surfaceContainerLow
+    backgroundColor: Color = MaterialTheme.colorScheme.surfaceContainerLow,
+    //外部定义末尾的图标按钮
+    trailingIcon: @Composable (() -> Unit)? = null,
+    //外部定义下拉菜单的内容
+    dropdownMenu: (@Composable (onDismiss: () -> Unit) -> Unit)? = null
 ) {
+    var showMenu by remember { mutableStateOf(false) }
+
     Surface(
         modifier = Modifier
             .fillMaxWidth()
@@ -35,17 +54,47 @@ fun SearchBarSection(
         color = backgroundColor
     ) {
         TextField(
+            value = query,
+            onValueChange = onQueryChange,
             modifier = Modifier
                 .fillMaxWidth()
                 .padding(horizontal = 4.dp),
-            value = query,
-            onValueChange = onQueryChange,
             placeholder = { Text(placeholder) },
             leadingIcon = { Icon(Icons.Default.Search, null) },
             trailingIcon = {
-                if (query.isNotEmpty()) {
-                    IconButton(onClick = { onQueryChange("") }) {
-                        Icon(Icons.Default.Clear, null)
+                Row(
+                    verticalAlignment = Alignment.CenterVertically,
+                    modifier = Modifier.padding(end = 4.dp)
+                ) {
+                    AnimatedVisibility(
+                        visible = query.isNotEmpty(),
+                        enter = fadeIn() + scaleIn(initialScale = 0.8f),
+                        exit = fadeOut() + scaleOut(targetScale = 0.8f)
+                    ) {
+                        IconButton(onClick = {
+                            onQueryChange("")
+                        }) {
+                            Icon(Icons.Default.Clear, "清空输入")
+                        }
+                    }
+
+                    if (trailingIcon != null) {
+                        Box {
+                            IconButton(onClick = {
+                                if (dropdownMenu != null) showMenu = true
+                            }) {
+                                trailingIcon()
+                            }
+
+                            if (dropdownMenu != null) {
+                                DropdownMenu(
+                                    expanded = showMenu,
+                                    onDismissRequest = { showMenu = false }
+                                ) {
+                                    dropdownMenu { showMenu = false }
+                                }
+                            }
+                        }
                     }
                 }
             },
@@ -59,4 +108,4 @@ fun SearchBarSection(
             )
         )
     }
-}
+}

+ 8 - 4
app/src/main/java/io/legado/app/ui/widget/components/SettingItem.kt

@@ -1,8 +1,8 @@
 package io.legado.app.ui.widget.components
 
+import androidx.compose.animation.animateContentSize
 import androidx.compose.foundation.combinedClickable
 import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
@@ -10,6 +10,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.ChevronRight
 import androidx.compose.material.icons.filled.Info
+import androidx.compose.material3.Card
 import androidx.compose.material3.DropdownMenu
 import androidx.compose.material3.Icon
 import androidx.compose.material3.ListItem
@@ -22,7 +23,6 @@ import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clip
 import androidx.compose.ui.graphics.painter.Painter
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.text.style.TextOverflow
@@ -103,10 +103,14 @@ fun SettingItem(
 ) {
     var showMenu by remember { mutableStateOf(false) }
 
-    Box ( modifier = Modifier.fillMaxWidth() ){
+    Card(
+        modifier = Modifier
+            .fillMaxWidth()
+            .animateContentSize(),
+        shape = RoundedCornerShape(8.dp)
+    ) {
         ListItem(
             modifier = modifier
-                .clip(RoundedCornerShape(4.dp))
                 .combinedClickable(
                     onClick = onClick,
                     onLongClick = {

+ 1 - 2
app/src/main/res/layout/fragment_bookshelf1.xml

@@ -19,8 +19,7 @@
             android:layout_width="match_parent"
             android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
             style="?attr/collapsingToolbarLayoutMediumStyle"
-            app:collapsedTitleTextAppearance="?attr/textAppearanceTitleLarge"
-            app:expandedTitleTextAppearance="?attr/textAppearanceHeadlineLarge"
+            app:expandedTitleTextAppearance="?attr/textAppearanceHeadlineMedium"
             app:titleCollapseMode="scale"
             app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
 

+ 1 - 2
app/src/main/res/layout/fragment_bookshelf2.xml

@@ -18,8 +18,7 @@
             style="?attr/collapsingToolbarLayoutMediumStyle"
             android:layout_width="match_parent"
             android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
-            app:collapsedTitleTextAppearance="?attr/textAppearanceTitleLarge"
-            app:expandedTitleTextAppearance="?attr/textAppearanceHeadlineLarge"
+            app:expandedTitleTextAppearance="?attr/textAppearanceHeadlineMedium"
             app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
             app:titleCollapseMode="scale">
 

+ 1 - 2
app/src/main/res/layout/fragment_bookshelf3.xml

@@ -19,8 +19,7 @@
             android:layout_width="match_parent"
             android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
             style="?attr/collapsingToolbarLayoutLargeStyle"
-            app:collapsedTitleTextAppearance="?attr/textAppearanceTitleLarge"
-            app:expandedTitleTextAppearance="?attr/textAppearanceHeadlineLarge"
+            app:expandedTitleTextAppearance="?attr/textAppearanceHeadlineMedium"
             app:titleCollapseMode="scale"
             app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
 

+ 2 - 3
app/src/main/res/layout/fragment_explore.xml

@@ -17,10 +17,9 @@
 
         <com.google.android.material.appbar.CollapsingToolbarLayout
             android:layout_width="match_parent"
-            android:layout_height="?attr/collapsingToolbarLayoutLargeSize"
+            android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
             style="?attr/collapsingToolbarLayoutLargeSize"
-            app:collapsedTitleTextAppearance="?attr/textAppearanceTitleLarge"
-            app:expandedTitleTextAppearance="?attr/textAppearanceHeadlineLarge"
+            app:expandedTitleTextAppearance="?attr/textAppearanceHeadlineMedium"
             app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
 
             <com.google.android.material.appbar.MaterialToolbar

+ 2 - 3
app/src/main/res/layout/fragment_rss.xml

@@ -16,10 +16,9 @@
 
         <com.google.android.material.appbar.CollapsingToolbarLayout
             android:layout_width="match_parent"
-            android:layout_height="?attr/collapsingToolbarLayoutLargeSize"
+            android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
             style="?attr/collapsingToolbarLayoutLargeSize"
-            app:collapsedTitleTextAppearance="?attr/textAppearanceTitleLarge"
-            app:expandedTitleTextAppearance="?attr/textAppearanceHeadlineLarge"
+            app:expandedTitleTextAppearance="?attr/textAppearanceHeadlineMedium"
             app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
 
             <com.google.android.material.appbar.MaterialToolbar