diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt b/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt index ada5344fd891..b106ca997ac7 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt @@ -48,29 +48,36 @@ enum class Flag( * Color for the background of cards with this flag in the card browser. */ @ColorRes val browserColorRes: Int?, + /** + * Color for the flag icon in the reviewer. + */ + @ColorRes val iconColorRes: Int?, ) { - NONE(0, R.id.flag_none, R.drawable.ic_flag_transparent, browserColorRes = null), - RED(1, R.id.flag_red, R.drawable.ic_flag_red, R.color.flag_red), + NONE(0, R.id.flag_none, R.drawable.ic_flag_transparent, browserColorRes = null, iconColorRes = null), + RED(1, R.id.flag_red, R.drawable.ic_flag_red, R.color.flag_red, R.color.flag_reviewer_red), ORANGE( 2, R.id.flag_orange, R.drawable.ic_flag_orange, R.color.flag_orange, + R.color.flag_reviewer_orange, ), - GREEN(3, R.id.flag_green, R.drawable.ic_flag_green, R.color.flag_green), - BLUE(4, R.id.flag_blue, R.drawable.ic_flag_blue, R.color.flag_blue), - PINK(5, R.id.flag_pink, R.drawable.ic_flag_pink, R.color.flag_pink), + GREEN(3, R.id.flag_green, R.drawable.ic_flag_green, R.color.flag_green, R.color.flag_reviewer_green), + BLUE(4, R.id.flag_blue, R.drawable.ic_flag_blue, R.color.flag_blue, R.color.flag_reviewer_blue), + PINK(5, R.id.flag_pink, R.drawable.ic_flag_pink, R.color.flag_pink, R.color.flag_reviewer_pink), TURQUOISE( 6, R.id.flag_turquoise, R.drawable.ic_flag_turquoise, R.color.flag_turquoise, + R.color.flag_reviewer_turquoise, ), PURPLE( 7, R.id.flag_purple, R.drawable.ic_flag_purple, R.color.flag_purple, + R.color.flag_reviewer_purple, ), ; diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt b/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt index a699c6ef9dfe..6821f32fe44d 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt @@ -851,11 +851,17 @@ open class Reviewer : if (flagIcon != null) { if (currentCard != null) { val flag = currentCard!!.flag - flagIcon.setIcon(flag.drawableRes) - if (flag == Flag.NONE && actionButtons.status.flagsIsOverflown()) { - val flagColor = ThemeUtils.getThemeAttrColor(this, android.R.attr.colorControlNormal) - flagIcon.icon?.mutate()?.setTint(flagColor) + val drawable = ContextCompat.getDrawable(this, flag.drawableRes)?.mutate() + val tint = + if (flag == Flag.NONE && actionButtons.status.flagsIsOverflown()) { + ThemeUtils.getThemeAttrColor(this, android.R.attr.colorControlNormal) + } else { + flag.iconColorRes?.let { ContextCompat.getColor(this, it) } + } + if (tint != null) { + drawable?.setTint(tint) } + flagIcon.icon = drawable } } @@ -1031,7 +1037,20 @@ open class Reviewer : private fun setupFlags(subMenu: SubMenu) { lifecycleScope.launch { for ((flag, displayName) in Flag.queryDisplayNames()) { - subMenu.findItem(flag.id).title = displayName + val item = subMenu.findItem(flag.id) + item.title = displayName + val drawable = ContextCompat.getDrawable(this@Reviewer, flag.drawableRes)?.mutate() + val tint = + if (flag == Flag.NONE) { + ThemeUtils.getThemeAttrColor(this@Reviewer, android.R.attr.colorControlNormal) + } else { + flag.iconColorRes?.let { ContextCompat.getColor(this@Reviewer, it) } + } + if (tint != null) { + drawable?.setTint(tint) + } + item.icon = drawable + flagItemIds.add(flag.id) } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserFragment.kt index d6742ca6ed21..09e8e7ea4315 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserFragment.kt @@ -317,14 +317,18 @@ class CardBrowserFragment : val subMenu = this lifecycleScope.launch { for ((flag, displayName) in Flag.queryDisplayNames()) { - val item = - subMenu - .add(flagGroupId, flag.code, Menu.NONE, displayName) - .setIcon(flag.drawableRes) - if (flag == Flag.NONE) { - val color = ThemeUtils.getThemeAttrColor(requireContext(), android.R.attr.colorControlNormal) - item.icon?.mutate()?.setTint(color) + val item = subMenu.add(flagGroupId, flag.code, Menu.NONE, displayName) + val drawable = ContextCompat.getDrawable(requireContext(), flag.drawableRes)?.mutate() + val tint = + if (flag == Flag.NONE) { + ThemeUtils.getThemeAttrColor(requireContext(), android.R.attr.colorControlNormal) + } else { + flag.iconColorRes?.let { ContextCompat.getColor(requireContext(), it) } + } + if (tint != null) { + drawable?.setTint(tint) } + item.icon = drawable } } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagAdapter.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagAdapter.kt index a5fa52f0bdac..2306534dd921 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagAdapter.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagAdapter.kt @@ -25,6 +25,7 @@ import android.view.inputmethod.InputMethodManager import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView +import androidx.core.content.ContextCompat import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView @@ -73,7 +74,12 @@ class FlagAdapter( ) { val flagItem = getItem(position) - holder.flagImageView.setImageResource(flagItem.icon) + val context = holder.flagImageView.context + val drawable = ContextCompat.getDrawable(context, flagItem.icon)?.mutate() + flagItem.flag.iconColorRes?.let { colorRes -> + drawable?.setTint(ContextCompat.getColor(context, colorRes)) + } + holder.flagImageView.setImageDrawable(drawable) holder.flagNameEditLayout.visibility = View.GONE diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/preferences/reviewer/ReviewerMenuView.kt b/AnkiDroid/src/main/java/com/ichi2/anki/preferences/reviewer/ReviewerMenuView.kt index 8a4e4ba1708b..49564c69193a 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/preferences/reviewer/ReviewerMenuView.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/preferences/reviewer/ReviewerMenuView.kt @@ -26,6 +26,7 @@ import android.widget.LinearLayout import androidx.appcompat.view.menu.MenuBuilder import androidx.appcompat.view.menu.MenuItemImpl import androidx.appcompat.widget.ActionMenuView +import androidx.core.content.ContextCompat import androidx.core.view.size import androidx.lifecycle.findViewTreeLifecycleOwner import androidx.lifecycle.lifecycleScope @@ -87,7 +88,7 @@ class ReviewerMenuView : LinearLayout { for (action in submenuActions) { val subMenu = findItem(action.parentMenu!!.menuId)?.subMenu ?: continue subMenu.add(Menu.NONE, action.menuId, Menu.NONE, action.title(context))?.apply { - action.drawableRes?.let { setIcon(it) } + setIconWithTint(action) } } } @@ -114,12 +115,23 @@ class ReviewerMenuView : LinearLayout { menu.add(Menu.NONE, action.menuId, Menu.NONE, title) } with(menuItem) { - action.drawableRes?.let { setIcon(it) } + setIconWithTint(action) setShowAsAction(menuActionType) } } } + private fun MenuItem.setIconWithTint(action: ViewerAction) { + val drawableRes = action.drawableRes ?: return + val drawable = ContextCompat.getDrawable(context, drawableRes)?.mutate() + val flag = Flag.entries.find { it.id == action.menuId } + val tintColorRes = flag?.iconColorRes + if (tintColorRes != null) { + drawable?.setTint(ContextCompat.getColor(context, tintColorRes)) + } + icon = drawable + } + private fun setupMenus() { val menuItems = repository.getActionsByMenuDisplayTypes(MenuDisplayType.ALWAYS, MenuDisplayType.MENU_ONLY) addActions(menuItems.getValue(MenuDisplayType.ALWAYS), menuItems.getValue(MenuDisplayType.MENU_ONLY)) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerFragment.kt index bc53b3b428cc..0b0e4bc8b7be 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerFragment.kt @@ -24,6 +24,7 @@ import android.view.Menu import android.view.MenuItem import android.view.View import androidx.appcompat.widget.Toolbar +import androidx.core.content.ContextCompat import androidx.core.os.bundleOf import androidx.core.view.ViewCompat import androidx.core.view.doOnLayout @@ -124,7 +125,13 @@ class PreviewerFragment : viewModel.flag .flowWithLifecycle(lifecycle) .collectLatest { flag -> - menu.findItem(R.id.action_flag).setIcon(flag.drawableRes) + val item = menu.findItem(R.id.action_flag) + val drawable = ContextCompat.getDrawable(requireContext(), flag.drawableRes)?.mutate() + val tint = flag.iconColorRes?.let { ContextCompat.getColor(requireContext(), it) } + if (tint != null) { + drawable?.setTint(tint) + } + item.icon = drawable } } @@ -204,9 +211,13 @@ class PreviewerFragment : val submenu = menu.findItem(R.id.action_flag).subMenu lifecycleScope.launch { for ((flag, name) in Flag.queryDisplayNames()) { - submenu - ?.add(Menu.NONE, flag.id, Menu.NONE, name) - ?.setIcon(flag.drawableRes) + val item = submenu?.add(Menu.NONE, flag.id, Menu.NONE, name) + val drawable = ContextCompat.getDrawable(requireContext(), flag.drawableRes)?.mutate() + val tint = flag.iconColorRes?.let { ContextCompat.getColor(requireContext(), it) } + if (tint != null) { + drawable?.setTint(tint) + } + item?.setIcon(drawable) } } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/reviewer/CardMarker.kt b/AnkiDroid/src/main/java/com/ichi2/anki/reviewer/CardMarker.kt index c5fd59594632..95c249770125 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/reviewer/CardMarker.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/reviewer/CardMarker.kt @@ -19,6 +19,7 @@ package com.ichi2.anki.reviewer import android.view.View import android.widget.ImageView import androidx.annotation.DrawableRes +import androidx.core.content.ContextCompat import androidx.core.view.isVisible import com.ichi2.anki.Flag import com.ichi2.anki.R @@ -46,7 +47,14 @@ class CardMarker( fun displayFlag(flag: Flag) { when (flag) { Flag.RED, Flag.BLUE, Flag.GREEN, Flag.ORANGE, Flag.PINK, Flag.PURPLE, Flag.TURQUOISE -> { - setFlagView(flag.drawableRes) + val context = flagView.context + val drawable = ContextCompat.getDrawable(context, flag.drawableRes)?.mutate() + val tint = flag.iconColorRes?.let { ContextCompat.getColor(context, it) } + if (tint != null) { + drawable?.setTint(tint) + } + flagView.setImageDrawable(drawable) + flagView.visibility = View.VISIBLE } Flag.NONE -> flagView.visibility = View.INVISIBLE } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt index 9781b5a52e58..8b7debc222d6 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt @@ -608,7 +608,11 @@ class ReviewerFragment : if (flag == Flag.NONE) { flagView.isVisible = false } else { - flagView.setImageDrawable(ContextCompat.getDrawable(requireContext(), flag.drawableRes)) + val drawable = ContextCompat.getDrawable(requireContext(), flag.drawableRes)?.mutate() + flag.iconColorRes?.let { colorRes -> + drawable?.setTint(ContextCompat.getColor(requireContext(), colorRes)) + } + flagView.setImageDrawable(drawable) flagView.isVisible = true } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerMenu.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerMenu.kt index 07b9ebe1fea0..6d89ffb2c2fc 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerMenu.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerMenu.kt @@ -17,6 +17,7 @@ package com.ichi2.anki.ui.windows.reviewer import android.view.Menu import androidx.appcompat.view.menu.SubMenuBuilder +import androidx.core.content.ContextCompat import androidx.core.view.isVisible import androidx.lifecycle.Lifecycle import androidx.lifecycle.coroutineScope @@ -41,8 +42,9 @@ fun ReviewerMenuView.setup( viewModel.flagFlow .flowWithLifecycle(lifecycle) - .collectLatestIn(lifecycle.coroutineScope) { flagCode -> - findItem(ViewerAction.FLAG_MENU.menuId)?.setPaddedIcon(context, flagCode.drawableRes) + .collectLatestIn(lifecycle.coroutineScope) { flag -> + val tint = flag.iconColorRes?.let { ContextCompat.getColor(context, it) } + findItem(ViewerAction.FLAG_MENU.menuId)?.setPaddedIcon(context, flag.drawableRes, tint = tint) } val markItem = findItem(ViewerAction.MARK.menuId) diff --git a/AnkiDroid/src/main/java/com/ichi2/utils/MenuUtils.kt b/AnkiDroid/src/main/java/com/ichi2/utils/MenuUtils.kt index 5d605ab78a66..0e423567765e 100644 --- a/AnkiDroid/src/main/java/com/ichi2/utils/MenuUtils.kt +++ b/AnkiDroid/src/main/java/com/ichi2/utils/MenuUtils.kt @@ -69,9 +69,13 @@ fun MenuItem.setPaddedIcon( context: Context, @DrawableRes drawableResId: Int, horizontalPaddingDp: Float = DEFAULT_HORIZONTAL_PADDING, + tint: Int? = null, ) { val padding = horizontalPaddingDp.dp.toPx(context) - val drawable = ContextCompat.getDrawable(context, drawableResId) + val drawable = ContextCompat.getDrawable(context, drawableResId)?.mutate() + if (tint != null) { + drawable?.setTint(tint) + } icon = InsetDrawable(drawable, padding, 0, padding, 0) }