Migrate reader shortcut menus to Compose
Contents' UIs should probably be improved, but that can happen separately.
This commit is contained in:
parent
400ca48456
commit
7308090288
10 changed files with 161 additions and 117 deletions
|
@ -0,0 +1,56 @@
|
||||||
|
package eu.kanade.presentation.reader
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.FilterChip
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import eu.kanade.domain.manga.model.orientationType
|
||||||
|
import eu.kanade.presentation.components.AdaptiveSheet
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
|
||||||
|
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
|
||||||
|
import tachiyomi.presentation.core.components.SettingsChipRow
|
||||||
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
|
|
||||||
|
private val orientationTypeOptions = OrientationType.entries.map { it.stringRes to it }
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun OrientationModeSelectDialog(
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
screenModel: ReaderSettingsScreenModel,
|
||||||
|
onChange: (Int) -> Unit,
|
||||||
|
) {
|
||||||
|
val manga by screenModel.mangaFlow.collectAsState()
|
||||||
|
val orientationType = remember(manga) { OrientationType.fromPreference(manga?.orientationType?.toInt()) }
|
||||||
|
|
||||||
|
AdaptiveSheet(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.padding(vertical = 16.dp),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
|
||||||
|
) {
|
||||||
|
SettingsChipRow(R.string.rotation_type) {
|
||||||
|
orientationTypeOptions.map { (stringRes, it) ->
|
||||||
|
FilterChip(
|
||||||
|
selected = it == orientationType,
|
||||||
|
onClick = {
|
||||||
|
screenModel.onChangeOrientation(it)
|
||||||
|
onChange(stringRes)
|
||||||
|
},
|
||||||
|
label = { Text(stringResource(stringRes)) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package eu.kanade.tachiyomi.ui.reader
|
package eu.kanade.presentation.reader
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
|
@ -0,0 +1,56 @@
|
||||||
|
package eu.kanade.presentation.reader
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.FilterChip
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import eu.kanade.domain.manga.model.readingModeType
|
||||||
|
import eu.kanade.presentation.components.AdaptiveSheet
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
|
||||||
|
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
|
||||||
|
import tachiyomi.presentation.core.components.SettingsChipRow
|
||||||
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
|
|
||||||
|
private val readingModeOptions = ReadingModeType.entries.map { it.stringRes to it }
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ReadingModeSelectDialog(
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
screenModel: ReaderSettingsScreenModel,
|
||||||
|
onChange: (Int) -> Unit,
|
||||||
|
) {
|
||||||
|
val manga by screenModel.mangaFlow.collectAsState()
|
||||||
|
val readingMode = remember(manga) { ReadingModeType.fromPreference(manga?.readingModeType?.toInt()) }
|
||||||
|
|
||||||
|
AdaptiveSheet(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.padding(vertical = 16.dp),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
|
||||||
|
) {
|
||||||
|
SettingsChipRow(R.string.pref_category_reading_mode) {
|
||||||
|
readingModeOptions.map { (stringRes, it) ->
|
||||||
|
FilterChip(
|
||||||
|
selected = it == readingMode,
|
||||||
|
onClick = {
|
||||||
|
screenModel.onChangeReadingMode(it)
|
||||||
|
onChange(stringRes)
|
||||||
|
},
|
||||||
|
label = { Text(stringResource(stringRes)) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,11 +42,12 @@ internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) {
|
||||||
pref = screenModel.preferences.fullscreen(),
|
pref = screenModel.preferences.fullscreen(),
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: hide if there's no cutout
|
if (screenModel.hasDisplayCutout) {
|
||||||
CheckboxItem(
|
CheckboxItem(
|
||||||
label = stringResource(R.string.pref_cutout_short),
|
label = stringResource(R.string.pref_cutout_short),
|
||||||
pref = screenModel.preferences.cutoutShort(),
|
pref = screenModel.preferences.cutoutShort(),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
CheckboxItem(
|
CheckboxItem(
|
||||||
label = stringResource(R.string.pref_keep_screen_on),
|
label = stringResource(R.string.pref_keep_screen_on),
|
||||||
|
|
|
@ -49,9 +49,11 @@ import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
import com.google.android.material.transition.platform.MaterialContainerTransform
|
import com.google.android.material.transition.platform.MaterialContainerTransform
|
||||||
import dev.chrisbanes.insetter.applyInsetter
|
import dev.chrisbanes.insetter.applyInsetter
|
||||||
import eu.kanade.domain.base.BasePreferences
|
import eu.kanade.domain.base.BasePreferences
|
||||||
import eu.kanade.domain.manga.model.orientationType
|
|
||||||
import eu.kanade.presentation.reader.ChapterNavigator
|
import eu.kanade.presentation.reader.ChapterNavigator
|
||||||
|
import eu.kanade.presentation.reader.OrientationModeSelectDialog
|
||||||
import eu.kanade.presentation.reader.PageIndicatorText
|
import eu.kanade.presentation.reader.PageIndicatorText
|
||||||
|
import eu.kanade.presentation.reader.ReaderPageActionsDialog
|
||||||
|
import eu.kanade.presentation.reader.ReadingModeSelectDialog
|
||||||
import eu.kanade.presentation.reader.settings.ReaderSettingsDialog
|
import eu.kanade.presentation.reader.settings.ReaderSettingsDialog
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||||
|
@ -79,7 +81,6 @@ import eu.kanade.tachiyomi.util.system.isNightMode
|
||||||
import eu.kanade.tachiyomi.util.system.toShareIntent
|
import eu.kanade.tachiyomi.util.system.toShareIntent
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.view.copy
|
import eu.kanade.tachiyomi.util.view.copy
|
||||||
import eu.kanade.tachiyomi.util.view.popupMenu
|
|
||||||
import eu.kanade.tachiyomi.util.view.setComposeContent
|
import eu.kanade.tachiyomi.util.view.setComposeContent
|
||||||
import eu.kanade.tachiyomi.util.view.setTooltip
|
import eu.kanade.tachiyomi.util.view.setTooltip
|
||||||
import eu.kanade.tachiyomi.widget.listener.SimpleAnimationListener
|
import eu.kanade.tachiyomi.widget.listener.SimpleAnimationListener
|
||||||
|
@ -124,7 +125,7 @@ class ReaderActivity : BaseActivity() {
|
||||||
val viewModel by viewModels<ReaderViewModel>()
|
val viewModel by viewModels<ReaderViewModel>()
|
||||||
private var assistUrl: String? = null
|
private var assistUrl: String? = null
|
||||||
|
|
||||||
val hasCutout by lazy { hasDisplayCutout() }
|
private val hasCutout by lazy { hasDisplayCutout() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration at reader level, like background color or forced orientation.
|
* Configuration at reader level, like background color or forced orientation.
|
||||||
|
@ -393,6 +394,7 @@ class ReaderActivity : BaseActivity() {
|
||||||
val settingsScreenModel = remember {
|
val settingsScreenModel = remember {
|
||||||
ReaderSettingsScreenModel(
|
ReaderSettingsScreenModel(
|
||||||
readerState = viewModel.state,
|
readerState = viewModel.state,
|
||||||
|
hasDisplayCutout = hasCutout,
|
||||||
onChangeReadingMode = viewModel::setMangaReadingMode,
|
onChangeReadingMode = viewModel::setMangaReadingMode,
|
||||||
onChangeOrientation = viewModel::setMangaOrientationType,
|
onChangeOrientation = viewModel::setMangaOrientationType,
|
||||||
)
|
)
|
||||||
|
@ -423,6 +425,30 @@ class ReaderActivity : BaseActivity() {
|
||||||
screenModel = settingsScreenModel,
|
screenModel = settingsScreenModel,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
is ReaderViewModel.Dialog.ReadingModeSelect -> {
|
||||||
|
ReadingModeSelectDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
screenModel = settingsScreenModel,
|
||||||
|
onChange = { stringRes ->
|
||||||
|
menuToggleToast?.cancel()
|
||||||
|
if (!readerPreferences.showReadingMode().get()) {
|
||||||
|
menuToggleToast = toast(stringRes)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCropBordersShortcut()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is ReaderViewModel.Dialog.OrientationModeSelect -> {
|
||||||
|
OrientationModeSelectDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
screenModel = settingsScreenModel,
|
||||||
|
onChange = { stringRes ->
|
||||||
|
menuToggleToast?.cancel()
|
||||||
|
menuToggleToast = toast(stringRes)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
is ReaderViewModel.Dialog.PageActions -> {
|
is ReaderViewModel.Dialog.PageActions -> {
|
||||||
ReaderPageActionsDialog(
|
ReaderPageActionsDialog(
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
|
@ -484,21 +510,7 @@ class ReaderActivity : BaseActivity() {
|
||||||
setTooltip(R.string.viewer)
|
setTooltip(R.string.viewer)
|
||||||
|
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
popupMenu(
|
viewModel.openReadingModeSelectDialog()
|
||||||
items = ReadingModeType.entries.map { it.flagValue to it.stringRes },
|
|
||||||
selectedItemId = viewModel.getMangaReadingMode(resolveDefault = false),
|
|
||||||
) {
|
|
||||||
val newReadingMode = ReadingModeType.fromPreference(itemId)
|
|
||||||
|
|
||||||
viewModel.setMangaReadingMode(newReadingMode)
|
|
||||||
|
|
||||||
menuToggleToast?.cancel()
|
|
||||||
if (!readerPreferences.showReadingMode().get()) {
|
|
||||||
menuToggleToast = toast(newReadingMode.stringRes)
|
|
||||||
}
|
|
||||||
|
|
||||||
updateCropBordersShortcut()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,18 +549,7 @@ class ReaderActivity : BaseActivity() {
|
||||||
setTooltip(R.string.rotation_type)
|
setTooltip(R.string.rotation_type)
|
||||||
|
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
popupMenu(
|
viewModel.openOrientationModeSelectDialog()
|
||||||
items = OrientationType.entries.map { it.flagValue to it.stringRes },
|
|
||||||
selectedItemId = viewModel.manga?.orientationType?.toInt()
|
|
||||||
?: readerPreferences.defaultOrientationType().get(),
|
|
||||||
) {
|
|
||||||
val newOrientation = OrientationType.fromPreference(itemId)
|
|
||||||
|
|
||||||
viewModel.setMangaOrientationType(newOrientation)
|
|
||||||
|
|
||||||
menuToggleToast?.cancel()
|
|
||||||
menuToggleToast = toast(newOrientation.stringRes)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -683,6 +683,14 @@ class ReaderViewModel(
|
||||||
mutableState.update { it.copy(dialog = Dialog.Loading) }
|
mutableState.update { it.copy(dialog = Dialog.Loading) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun openReadingModeSelectDialog() {
|
||||||
|
mutableState.update { it.copy(dialog = Dialog.ReadingModeSelect) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun openOrientationModeSelectDialog() {
|
||||||
|
mutableState.update { it.copy(dialog = Dialog.OrientationModeSelect) }
|
||||||
|
}
|
||||||
|
|
||||||
fun openPageDialog(page: ReaderPage) {
|
fun openPageDialog(page: ReaderPage) {
|
||||||
mutableState.update { it.copy(dialog = Dialog.PageActions(page)) }
|
mutableState.update { it.copy(dialog = Dialog.PageActions(page)) }
|
||||||
}
|
}
|
||||||
|
@ -863,6 +871,8 @@ class ReaderViewModel(
|
||||||
sealed interface Dialog {
|
sealed interface Dialog {
|
||||||
data object Loading : Dialog
|
data object Loading : Dialog
|
||||||
data object Settings : Dialog
|
data object Settings : Dialog
|
||||||
|
data object ReadingModeSelect : Dialog
|
||||||
|
data object OrientationModeSelect : Dialog
|
||||||
data class PageActions(val page: ReaderPage) : Dialog
|
data class PageActions(val page: ReaderPage) : Dialog
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
class ReaderSettingsScreenModel(
|
class ReaderSettingsScreenModel(
|
||||||
readerState: StateFlow<ReaderViewModel.State>,
|
readerState: StateFlow<ReaderViewModel.State>,
|
||||||
|
val hasDisplayCutout: Boolean,
|
||||||
val onChangeReadingMode: (ReadingModeType) -> Unit,
|
val onChangeReadingMode: (ReadingModeType) -> Unit,
|
||||||
val onChangeOrientation: (OrientationType) -> Unit,
|
val onChangeOrientation: (OrientationType) -> Unit,
|
||||||
val preferences: ReaderPreferences = Injekt.get(),
|
val preferences: ReaderPreferences = Injekt.get(),
|
||||||
|
|
|
@ -7,20 +7,13 @@ import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
import androidx.annotation.AttrRes
|
|
||||||
import androidx.annotation.ColorInt
|
|
||||||
import androidx.appcompat.view.ContextThemeWrapper
|
import androidx.appcompat.view.ContextThemeWrapper
|
||||||
import androidx.core.content.PermissionChecker
|
import androidx.core.content.PermissionChecker
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import androidx.core.graphics.alpha
|
|
||||||
import androidx.core.graphics.blue
|
|
||||||
import androidx.core.graphics.green
|
|
||||||
import androidx.core.graphics.red
|
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import com.hippo.unifile.UniFile
|
import com.hippo.unifile.UniFile
|
||||||
import eu.kanade.domain.ui.UiPreferences
|
import eu.kanade.domain.ui.UiPreferences
|
||||||
|
@ -35,7 +28,6 @@ import tachiyomi.core.util.system.logcat
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies a string to clipboard
|
* Copies a string to clipboard
|
||||||
|
@ -69,25 +61,6 @@ fun Context.copyToClipboard(label: String, content: String) {
|
||||||
*/
|
*/
|
||||||
fun Context.hasPermission(permission: String) = PermissionChecker.checkSelfPermission(this, permission) == PermissionChecker.PERMISSION_GRANTED
|
fun Context.hasPermission(permission: String) = PermissionChecker.checkSelfPermission(this, permission) == PermissionChecker.PERMISSION_GRANTED
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the color for the given attribute.
|
|
||||||
*
|
|
||||||
* @param resource the attribute.
|
|
||||||
* @param alphaFactor the alpha number [0,1].
|
|
||||||
*/
|
|
||||||
@ColorInt fun Context.getResourceColor(@AttrRes resource: Int, alphaFactor: Float = 1f): Int {
|
|
||||||
val typedArray = obtainStyledAttributes(intArrayOf(resource))
|
|
||||||
val color = typedArray.getColor(0, 0)
|
|
||||||
typedArray.recycle()
|
|
||||||
|
|
||||||
if (alphaFactor < 1f) {
|
|
||||||
val alpha = (color.alpha * alphaFactor).roundToInt()
|
|
||||||
return Color.argb(alpha, color.red, color.green, color.blue)
|
|
||||||
}
|
|
||||||
|
|
||||||
return color
|
|
||||||
}
|
|
||||||
|
|
||||||
val Context.powerManager: PowerManager
|
val Context.powerManager: PowerManager
|
||||||
get() = getSystemService()!!
|
get() = getSystemService()!!
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
package eu.kanade.tachiyomi.util.view
|
package eu.kanade.tachiyomi.util.view
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
|
@ -15,8 +14,6 @@ import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.annotation.MenuRes
|
import androidx.annotation.MenuRes
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.appcompat.content.res.AppCompatResources
|
|
||||||
import androidx.appcompat.view.menu.MenuBuilder
|
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
import androidx.appcompat.widget.TooltipCompat
|
import androidx.appcompat.widget.TooltipCompat
|
||||||
import androidx.compose.material3.LocalContentColor
|
import androidx.compose.material3.LocalContentColor
|
||||||
|
@ -27,11 +24,9 @@ import androidx.compose.runtime.CompositionContext
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.ui.platform.ComposeView
|
import androidx.compose.ui.platform.ComposeView
|
||||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||||
import androidx.core.view.forEach
|
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
|
||||||
|
|
||||||
inline fun ComponentActivity.setComposeContent(
|
inline fun ComponentActivity.setComposeContent(
|
||||||
parent: CompositionContext? = null,
|
parent: CompositionContext? = null,
|
||||||
|
@ -110,46 +105,6 @@ inline fun View.popupMenu(
|
||||||
return popup
|
return popup
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows a popup menu on top of this view.
|
|
||||||
*
|
|
||||||
* @param items menu item names to inflate the menu with. List of itemId to stringRes pairs.
|
|
||||||
* @param selectedItemId optionally show a checkmark beside an item with this itemId.
|
|
||||||
* @param onMenuItemClick function to execute when a menu item is clicked.
|
|
||||||
*/
|
|
||||||
@SuppressLint("RestrictedApi")
|
|
||||||
inline fun View.popupMenu(
|
|
||||||
items: List<Pair<Int, Int>>,
|
|
||||||
selectedItemId: Int? = null,
|
|
||||||
noinline onMenuItemClick: MenuItem.() -> Unit,
|
|
||||||
): PopupMenu {
|
|
||||||
val popup = PopupMenu(context, this, Gravity.NO_GRAVITY, R.attr.actionOverflowMenuStyle, 0)
|
|
||||||
items.forEach { (id, stringRes) ->
|
|
||||||
popup.menu.add(0, id, 0, stringRes)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedItemId != null) {
|
|
||||||
(popup.menu as? MenuBuilder)?.setOptionalIconsVisible(true)
|
|
||||||
val emptyIcon = AppCompatResources.getDrawable(context, R.drawable.ic_blank_24dp)
|
|
||||||
popup.menu.forEach { item ->
|
|
||||||
item.icon = when (item.itemId) {
|
|
||||||
selectedItemId -> AppCompatResources.getDrawable(context, R.drawable.ic_check_24dp)?.mutate()?.apply {
|
|
||||||
setTint(context.getResourceColor(android.R.attr.textColorPrimary))
|
|
||||||
}
|
|
||||||
else -> emptyIcon
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
popup.setOnMenuItemClickListener {
|
|
||||||
it.onMenuItemClick()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
popup.show()
|
|
||||||
return popup
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a deep copy of the provided [Drawable]
|
* Returns a deep copy of the provided [Drawable]
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24.0"
|
|
||||||
android:viewportHeight="24.0">
|
|
||||||
<path
|
|
||||||
android:fillColor="#000"
|
|
||||||
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z" />
|
|
||||||
</vector>
|
|
Reference in a new issue