[修复] 修复一些问题
This commit is contained in:
@@ -16,13 +16,11 @@ import android.graphics.drawable.TransitionDrawable
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.method.ScrollingMovementMethod
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.CheckBox
|
||||
import android.widget.LinearLayout
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.addCallback
|
||||
import androidx.activity.viewModels
|
||||
import androidx.core.app.ActivityCompat
|
||||
@@ -54,7 +52,6 @@ import io.legado.app.help.book.isAudio
|
||||
import io.legado.app.help.book.isImage
|
||||
import io.legado.app.help.book.isLocal
|
||||
import io.legado.app.help.book.isLocalTxt
|
||||
import io.legado.app.help.book.isNotShelf
|
||||
import io.legado.app.help.book.isWebFile
|
||||
import io.legado.app.help.book.removeType
|
||||
import io.legado.app.help.config.AppConfig
|
||||
@@ -62,7 +59,6 @@ import io.legado.app.help.config.LocalConfig
|
||||
import io.legado.app.lib.dialogs.alert
|
||||
import io.legado.app.lib.dialogs.selector
|
||||
import io.legado.app.model.BookCover
|
||||
import io.legado.app.model.ReadBook
|
||||
import io.legado.app.model.remote.RemoteBookWebDav
|
||||
import io.legado.app.ui.about.AppLogDialog
|
||||
import io.legado.app.ui.book.audio.AudioPlayActivity
|
||||
@@ -158,7 +154,6 @@ class BookInfoActivity :
|
||||
viewModel.refreshBook(book)
|
||||
}
|
||||
}
|
||||
private lateinit var backCallback: OnBackPressedCallback
|
||||
private var surfaceFinalColor: Int = 0
|
||||
private var surfaceContainerFinalColor: Int = 0
|
||||
private var secondaryFinalColor: Int = 0
|
||||
@@ -178,7 +173,6 @@ class BookInfoActivity :
|
||||
|
||||
@SuppressLint("PrivateResource")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
postponeEnterTransition()
|
||||
setEnterSharedElementCallback(MaterialContainerTransformSharedElementCallback())
|
||||
setExitSharedElementCallback(MaterialContainerTransformSharedElementCallback())
|
||||
val transform = MaterialContainerTransform().apply {
|
||||
@@ -187,7 +181,6 @@ class BookInfoActivity :
|
||||
}
|
||||
window.sharedElementEnterTransition = transform
|
||||
window.sharedElementReturnTransition = transform
|
||||
window.sharedElementsUseOverlay = false
|
||||
super.onCreate(savedInstanceState)
|
||||
setupBackCallback()
|
||||
surfaceFinalColor =
|
||||
@@ -389,7 +382,7 @@ class BookInfoActivity :
|
||||
|
||||
private fun setupBackCallback() {
|
||||
onBackPressedDispatcher.addCallback(this) {
|
||||
if (!viewModel.inBookshelf) {
|
||||
if (!viewModel.inBookshelf && AppConfig.showAddToShelfAlert) {
|
||||
viewModel.getBook()?.let { book ->
|
||||
alert(title = getString(R.string.add_to_bookshelf)) {
|
||||
setMessage(getString(R.string.check_add_bookshelf, book.name))
|
||||
@@ -442,7 +435,7 @@ class BookInfoActivity :
|
||||
addColorScheme(binding.ivCover.drawable)
|
||||
tvName.text = book.name
|
||||
tvRemark.text = book.remark
|
||||
if (book.remark == null)
|
||||
if (book.remark.isNullOrEmpty())
|
||||
cdRemark.gone()
|
||||
else
|
||||
cdRemark.visible()
|
||||
|
||||
@@ -19,7 +19,12 @@ class BookInfoEditActivity : BaseComposeActivity(), ChangeCoverDialog.CallBack {
|
||||
BookInfoEditScreen(
|
||||
viewModel = viewModel,
|
||||
onBack = { finish() },
|
||||
onSave = ::saveData
|
||||
onSave = {
|
||||
viewModel.save {
|
||||
setResult(RESULT_OK)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -32,16 +37,9 @@ class BookInfoEditActivity : BaseComposeActivity(), ChangeCoverDialog.CallBack {
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveData() {
|
||||
viewModel.saveBook {
|
||||
setResult(RESULT_OK)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
override fun coverChangeTo(coverUrl: String) {
|
||||
// 更新封面 URL
|
||||
viewModel.updateCoverUrl(coverUrl)
|
||||
viewModel.onCoverUrlChange(coverUrl)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ 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.filled.FolderOpen
|
||||
import androidx.compose.material.icons.filled.ImageSearch
|
||||
import androidx.compose.material.icons.filled.Replay
|
||||
import androidx.compose.material.icons.filled.Save
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
@@ -21,16 +23,16 @@ import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.ExposedDropdownMenuAnchorType
|
||||
import androidx.compose.material3.ExposedDropdownMenuBox
|
||||
import androidx.compose.material3.ExposedDropdownMenuDefaults
|
||||
import androidx.compose.material3.FilledTonalButton
|
||||
import androidx.compose.material3.FilledTonalIconButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.IconButtonDefaults
|
||||
import androidx.compose.material3.MediumTopAppBar
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
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
|
||||
@@ -43,9 +45,6 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import io.legado.app.R
|
||||
import io.legado.app.data.entities.Book
|
||||
import io.legado.app.help.book.isAudio
|
||||
import io.legado.app.help.book.isImage
|
||||
import io.legado.app.ui.book.changecover.ChangeCoverDialog
|
||||
import io.legado.app.ui.widget.components.Cover
|
||||
import io.legado.app.utils.SelectImageContract
|
||||
@@ -59,7 +58,7 @@ fun BookInfoEditScreen(
|
||||
onBack: () -> Unit,
|
||||
onSave: () -> Unit
|
||||
) {
|
||||
val book by viewModel.bookData.collectAsStateWithLifecycle()
|
||||
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
|
||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||
|
||||
Scaffold(
|
||||
@@ -76,7 +75,9 @@ fun BookInfoEditScreen(
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
FilledTonalButton(onClick = onSave) {
|
||||
FilledTonalIconButton(
|
||||
onClick = { viewModel.save(onSave) },
|
||||
shapes = IconButtonDefaults.shapes()) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Save,
|
||||
contentDescription = stringResource(id = R.string.action_save)
|
||||
@@ -87,13 +88,13 @@ fun BookInfoEditScreen(
|
||||
)
|
||||
},
|
||||
content = { paddingValues ->
|
||||
book?.let {
|
||||
uiState.book?.let {
|
||||
BookInfoEditContent(
|
||||
modifier = Modifier
|
||||
.padding(paddingValues)
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState()),
|
||||
book = it,
|
||||
uiState = uiState,
|
||||
viewModel = viewModel
|
||||
)
|
||||
}
|
||||
@@ -101,59 +102,56 @@ fun BookInfoEditScreen(
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Composable
|
||||
fun BookInfoEditContent(
|
||||
modifier: Modifier = Modifier,
|
||||
book: Book,
|
||||
uiState: BookInfoEditUiState,
|
||||
viewModel: BookInfoEditViewModel
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
var name by remember(book.name) { mutableStateOf(book.name) }
|
||||
var author by remember(book.author) { mutableStateOf(book.author) }
|
||||
var coverUrl by remember(book.customCoverUrl) { mutableStateOf(book.getDisplayCover()) }
|
||||
var intro by remember(book.customIntro) { mutableStateOf(book.getDisplayIntro()) }
|
||||
var remark by remember(book.remark) { mutableStateOf(book.remark) }
|
||||
|
||||
val bookTypes = arrayOf("文本", "音频", "图片")
|
||||
val selectedTypeIndex = when {
|
||||
book.isImage -> 2
|
||||
book.isAudio -> 1
|
||||
else -> 0
|
||||
}
|
||||
var selectedType by remember { mutableStateOf(bookTypes[selectedTypeIndex]) }
|
||||
|
||||
val selectCover = rememberLauncherForActivityResult(SelectImageContract()) {
|
||||
it.uri?.let { uri ->
|
||||
viewModel.coverChangeTo(context, uri) { newCoverUrl ->
|
||||
coverUrl = newCoverUrl
|
||||
}
|
||||
viewModel.coverChangeTo(context, uri)
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(coverUrl) {
|
||||
viewModel.book?.customCoverUrl = coverUrl
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = modifier.padding(16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Cover(
|
||||
path = coverUrl,
|
||||
path = uiState.coverUrl,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(0.3f)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
FilledTonalButton(onClick = {
|
||||
(context as? BookInfoEditActivity)?.showDialogFragment(ChangeCoverDialog(book.name, book.author))
|
||||
}) {
|
||||
Text("网络搜索")
|
||||
FilledTonalIconButton(
|
||||
onClick = {
|
||||
(context as? BookInfoEditActivity)?.showDialogFragment(
|
||||
ChangeCoverDialog(
|
||||
uiState.name,
|
||||
uiState.author
|
||||
)
|
||||
)
|
||||
},
|
||||
shapes = IconButtonDefaults.shapes()) {
|
||||
Icon(
|
||||
Icons.Default.ImageSearch,
|
||||
contentDescription = stringResource(id = R.string.default_cover)
|
||||
)
|
||||
}
|
||||
FilledTonalButton(onClick = { selectCover.launch() }) {
|
||||
Text("本地选择")
|
||||
FilledTonalIconButton(onClick = { selectCover.launch() },
|
||||
shapes = IconButtonDefaults.shapes()) {
|
||||
Icon(
|
||||
Icons.Default.FolderOpen,
|
||||
contentDescription = stringResource(id = R.string.default_cover)
|
||||
)
|
||||
}
|
||||
FilledTonalButton(onClick = { coverUrl = book.coverUrl ?: "" }) {
|
||||
FilledTonalIconButton(onClick = { viewModel.resetCover() },
|
||||
shapes = IconButtonDefaults.shapes()) {
|
||||
Icon(
|
||||
Icons.Default.Replay,
|
||||
contentDescription = stringResource(id = R.string.default_cover)
|
||||
@@ -162,57 +160,53 @@ fun BookInfoEditContent(
|
||||
}
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
OutlinedTextField(
|
||||
value = name,
|
||||
onValueChange = { name = it },
|
||||
value = uiState.name,
|
||||
onValueChange = { viewModel.onNameChange(it) },
|
||||
label = { Text("书名") },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
value = author,
|
||||
onValueChange = { author = it },
|
||||
value = uiState.author,
|
||||
onValueChange = { viewModel.onAuthorChange(it) },
|
||||
label = { Text("作者") },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
BookTypeDropdown(
|
||||
bookTypes = bookTypes,
|
||||
selectedType = selectedType,
|
||||
onTypeSelected = { selectedType = it }
|
||||
bookTypes = uiState.bookTypes,
|
||||
selectedType = uiState.selectedType,
|
||||
onTypeSelected = { viewModel.onBookTypeChange(it) }
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
value = coverUrl ?: "",
|
||||
onValueChange = { coverUrl = it },
|
||||
value = uiState.coverUrl ?: "",
|
||||
onValueChange = { viewModel.onCoverUrlChange(it) },
|
||||
label = { Text("封面链接") },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
value = intro ?: "",
|
||||
onValueChange = { intro = it },
|
||||
value = uiState.intro ?: "",
|
||||
onValueChange = { viewModel.onIntroChange(it) },
|
||||
label = { Text("简介") },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
maxLines = 5
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
value = remark ?: "",
|
||||
onValueChange = { remark = it },
|
||||
value = uiState.remark ?: "",
|
||||
onValueChange = { viewModel.onRemarkChange(it) },
|
||||
label = { Text("备注") },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
|
||||
LaunchedEffect(name, author, selectedType, coverUrl, intro, remark) {
|
||||
viewModel.updateBookState(name, author, selectedType, bookTypes, coverUrl, intro, remark)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun BookTypeDropdown(
|
||||
bookTypes: Array<String>,
|
||||
bookTypes: List<String>,
|
||||
selectedType: String,
|
||||
onTypeSelected: (String) -> Unit
|
||||
) {
|
||||
@@ -223,10 +217,12 @@ fun BookTypeDropdown(
|
||||
onExpandedChange = { expanded = !expanded }
|
||||
) {
|
||||
OutlinedTextField(
|
||||
modifier = Modifier.fillMaxWidth().menuAnchor(
|
||||
ExposedDropdownMenuAnchorType.PrimaryEditable,
|
||||
true
|
||||
),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.menuAnchor(
|
||||
ExposedDropdownMenuAnchorType.PrimaryEditable,
|
||||
true
|
||||
),
|
||||
readOnly = true,
|
||||
value = selectedType,
|
||||
onValueChange = {},
|
||||
|
||||
@@ -11,6 +11,8 @@ import io.legado.app.data.appDb
|
||||
import io.legado.app.data.entities.Book
|
||||
import io.legado.app.help.book.BookHelp
|
||||
import io.legado.app.help.book.addType
|
||||
import io.legado.app.help.book.isAudio
|
||||
import io.legado.app.help.book.isImage
|
||||
import io.legado.app.help.book.isLocal
|
||||
import io.legado.app.help.book.removeType
|
||||
import io.legado.app.model.ReadBook
|
||||
@@ -23,30 +25,99 @@ import kotlinx.coroutines.flow.asStateFlow
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
|
||||
data class BookInfoEditUiState(
|
||||
val name: String = "",
|
||||
val author: String = "",
|
||||
val coverUrl: String? = null,
|
||||
val intro: String? = null,
|
||||
val remark: String? = null,
|
||||
val selectedType: String = "文本",
|
||||
val bookTypes: List<String> = listOf("文本", "音频", "图片"),
|
||||
val book: Book? = null,
|
||||
)
|
||||
|
||||
class BookInfoEditViewModel(application: Application) : BaseViewModel(application) {
|
||||
var book: Book? = null
|
||||
private val _bookData = MutableStateFlow<Book?>(null)
|
||||
val bookData: StateFlow<Book?> = _bookData.asStateFlow()
|
||||
private val _uiState = MutableStateFlow(BookInfoEditUiState())
|
||||
val uiState: StateFlow<BookInfoEditUiState> = _uiState.asStateFlow()
|
||||
|
||||
fun loadBook(bookUrl: String) {
|
||||
execute {
|
||||
book = appDb.bookDao.getBook(bookUrl)
|
||||
book?.let {
|
||||
_bookData.value = it
|
||||
val selectedTypeIndex = when {
|
||||
it.isImage -> 2
|
||||
it.isAudio -> 1
|
||||
else -> 0
|
||||
}
|
||||
_uiState.value = BookInfoEditUiState(
|
||||
name = it.name,
|
||||
author = it.author,
|
||||
coverUrl = it.getDisplayCover(),
|
||||
intro = it.getDisplayIntro(),
|
||||
remark = it.remark,
|
||||
selectedType = _uiState.value.bookTypes[selectedTypeIndex],
|
||||
book = it
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun saveBook(success: (() -> Unit)?) {
|
||||
fun onNameChange(name: String) {
|
||||
_uiState.value = _uiState.value.copy(name = name)
|
||||
}
|
||||
|
||||
fun onAuthorChange(author: String) {
|
||||
_uiState.value = _uiState.value.copy(author = author)
|
||||
}
|
||||
|
||||
fun onCoverUrlChange(coverUrl: String) {
|
||||
_uiState.value = _uiState.value.copy(coverUrl = coverUrl)
|
||||
}
|
||||
|
||||
fun onIntroChange(intro: String) {
|
||||
_uiState.value = _uiState.value.copy(intro = intro)
|
||||
}
|
||||
|
||||
fun onRemarkChange(remark: String) {
|
||||
_uiState.value = _uiState.value.copy(remark = remark)
|
||||
}
|
||||
|
||||
fun onBookTypeChange(bookType: String) {
|
||||
_uiState.value = _uiState.value.copy(selectedType = bookType)
|
||||
}
|
||||
|
||||
fun resetCover() {
|
||||
_uiState.value = _uiState.value.copy(coverUrl = book?.coverUrl ?: "")
|
||||
}
|
||||
|
||||
fun save(onSuccess: () -> Unit) {
|
||||
execute {
|
||||
val currentState = _uiState.value
|
||||
book?.let { book ->
|
||||
val oldBook = book.copy()
|
||||
book.name = currentState.name
|
||||
book.author = currentState.author
|
||||
book.remark = currentState.remark
|
||||
val local = if (book.isLocal) BookType.local else 0
|
||||
val bookType = when (currentState.selectedType) {
|
||||
currentState.bookTypes[2] -> BookType.image or local
|
||||
currentState.bookTypes[1] -> BookType.audio or local
|
||||
else -> BookType.text or local
|
||||
}
|
||||
book.removeType(BookType.local, BookType.image, BookType.audio, BookType.text)
|
||||
book.addType(bookType)
|
||||
book.customCoverUrl = if (currentState.coverUrl == book.coverUrl) null else currentState.coverUrl
|
||||
book.customIntro = if (currentState.intro == book.intro) null else currentState.intro
|
||||
BookHelp.updateCacheFolder(oldBook, book)
|
||||
|
||||
if (ReadBook.book?.bookUrl == book.bookUrl) {
|
||||
ReadBook.book = book
|
||||
}
|
||||
appDb.bookDao.update(book)
|
||||
}
|
||||
}.onSuccess {
|
||||
success?.invoke()
|
||||
onSuccess.invoke()
|
||||
}.onError {
|
||||
if (it is SQLiteConstraintException) {
|
||||
AppLog.put("书籍信息保存失败,存在相同书名作者书籍\n$it", it, true)
|
||||
@@ -56,35 +127,7 @@ class BookInfoEditViewModel(application: Application) : BaseViewModel(applicatio
|
||||
}
|
||||
}
|
||||
|
||||
fun updateBookState(
|
||||
name: String,
|
||||
author: String,
|
||||
selectedType: String,
|
||||
bookTypes: Array<String>,
|
||||
coverUrl: String?,
|
||||
intro: String?,
|
||||
remark: String?
|
||||
) {
|
||||
book?.let { book ->
|
||||
val oldBook = book.copy()
|
||||
book.name = name
|
||||
book.author = author
|
||||
book.remark = remark
|
||||
val local = if (book.isLocal) BookType.local else 0
|
||||
val bookType = when (selectedType) {
|
||||
bookTypes[2] -> BookType.image or local
|
||||
bookTypes[1] -> BookType.audio or local
|
||||
else -> BookType.text or local
|
||||
}
|
||||
book.removeType(BookType.local, BookType.image, BookType.audio, BookType.text)
|
||||
book.addType(bookType)
|
||||
book.customCoverUrl = if (coverUrl == book.coverUrl) null else coverUrl
|
||||
book.customIntro = if (intro == book.intro) null else intro
|
||||
BookHelp.updateCacheFolder(oldBook, book)
|
||||
}
|
||||
}
|
||||
|
||||
fun coverChangeTo(context: Context, uri: Uri, onFinally: (coverUrl: String) -> Unit) {
|
||||
fun coverChangeTo(context: Context, uri: Uri) {
|
||||
execute {
|
||||
runCatching {
|
||||
context.externalCacheDir?.let { externalCacheDir ->
|
||||
@@ -97,7 +140,7 @@ class BookInfoEditViewModel(application: Application) : BaseViewModel(applicatio
|
||||
inputStream.copyTo(outputStream)
|
||||
}
|
||||
}
|
||||
onFinally(coverFile.absolutePath)
|
||||
_uiState.value = _uiState.value.copy(coverUrl = coverFile.absolutePath)
|
||||
} ?: run {
|
||||
AppLog.put("External cache directory is null", Throwable("Null directory"), true)
|
||||
}
|
||||
@@ -106,13 +149,4 @@ class BookInfoEditViewModel(application: Application) : BaseViewModel(applicatio
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun updateCoverUrl(coverUrl: String) {
|
||||
book?.let {
|
||||
val updatedBook = it.copy(customCoverUrl = coverUrl)
|
||||
_bookData.value = updatedBook
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -286,8 +286,6 @@ class ReadBookActivity : BaseReadBookActivity(),
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
||||
|
||||
setEnterSharedElementCallback(MaterialContainerTransformSharedElementCallback())
|
||||
setExitSharedElementCallback(MaterialContainerTransformSharedElementCallback())
|
||||
val transform = MaterialContainerTransform().apply {
|
||||
|
||||
Reference in New Issue
Block a user