Using a dialog for the full cover transition in manga details

which will optimize the blur by a lot

(also adding in the manga detail button styles from upstream, not using it for anything but save/share)
This commit is contained in:
Jays2Kings 2021-07-20 13:07:30 -04:00
parent 3c8e30606e
commit a0bc45af46
7 changed files with 387 additions and 262 deletions

View File

@ -0,0 +1,251 @@
package eu.kanade.tachiyomi.ui.manga
import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.app.Dialog
import android.graphics.Color
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.os.Build
import android.view.LayoutInflater
import android.view.View
import android.view.animation.DecelerateInterpolator
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.animation.addListener
import androidx.transition.ChangeBounds
import androidx.transition.ChangeImageTransform
import androidx.transition.TransitionManager
import androidx.transition.TransitionSet
import com.google.android.material.shape.CornerFamily
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.databinding.FullCoverDialogBinding
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.view.animateBlur
import eu.kanade.tachiyomi.util.view.updateLayoutParams
import uy.kohesive.injekt.injectLazy
class FullCoverDialog(val controller: MangaDetailsController, drawable: Drawable, val thumbView: View) :
Dialog(controller.activity!!, R.style.FullCoverDialogTheme) {
val activity = controller.activity
val binding = FullCoverDialogBinding.inflate(LayoutInflater.from(context), null, false)
val preferences: PreferencesHelper by injectLazy()
private val ratio = 5f.dpToPx
private val fullRatio = 0f
val shortAnimationDuration = (
activity?.resources?.getInteger(
android.R.integer.config_shortAnimTime
) ?: 0
).toLong()
init {
setContentView(binding.root)
binding.touchOutside.setOnClickListener {
onBackPressed()
}
binding.mangaCoverFull.setOnClickListener {
onBackPressed()
}
binding.btnSave.setOnClickListener {
controller.saveCover()
}
binding.btnShare.setOnClickListener {
controller.shareCover()
}
val expandedImageView = binding.mangaCoverFull
expandedImageView.shapeAppearanceModel =
expandedImageView.shapeAppearanceModel.toBuilder()
.setAllCorners(CornerFamily.ROUNDED, ratio)
.build()
expandedImageView.setImageDrawable(drawable)
val rect = Rect()
thumbView.getGlobalVisibleRect(rect)
val topInset = activity?.window?.decorView?.rootWindowInsets?.systemWindowInsetTop ?: 0
val leftInset = activity?.window?.decorView?.rootWindowInsets?.systemWindowInsetLeft ?: 0
val rightInset = activity?.window?.decorView?.rootWindowInsets?.systemWindowInsetRight ?: 0
expandedImageView.updateLayoutParams<ConstraintLayout.LayoutParams> {
height = thumbView.height
width = thumbView.width
topMargin = rect.top - topInset
leftMargin = rect.left - leftInset
rightMargin = rect.right - rightInset
bottomMargin = rect.bottom
horizontalBias = 0.0f
verticalBias = 0.0f
}
expandedImageView.requestLayout()
binding.btnShare.alpha = 0f
binding.btnSave.alpha = 0f
expandedImageView.post {
// Hide the thumbnail and show the zoomed-in view. When the animation
// begins, it will position the zoomed-in view in the place of the
// thumbnail.
thumbView.alpha = 0f
val defMargin = 16.dpToPx
if (Build.VERSION.SDK_INT >= 31) {
activity?.window?.decorView?.animateBlur(1f, 20f, 50)?.start()
}
expandedImageView.updateLayoutParams<ConstraintLayout.LayoutParams> {
height = 0
width = 0
topMargin = defMargin
leftMargin = defMargin
rightMargin = defMargin
bottomMargin = defMargin
horizontalBias = 0.5f
verticalBias = 0.5f
}
// TransitionSet for the full cover because using animation for this SUCKS
val transitionSet = TransitionSet()
val bound = ChangeBounds()
transitionSet.addTransition(bound)
val changeImageTransform = ChangeImageTransform()
transitionSet.addTransition(changeImageTransform)
transitionSet.duration = shortAnimationDuration
TransitionManager.beginDelayedTransition(binding.root, transitionSet)
AnimatorSet().apply {
val radiusAnimator = ValueAnimator.ofFloat(ratio, fullRatio).apply {
addUpdateListener {
val value = it.animatedValue as Float
expandedImageView.shapeAppearanceModel =
expandedImageView.shapeAppearanceModel.toBuilder()
.setAllCorners(CornerFamily.ROUNDED, value)
.build()
}
duration = shortAnimationDuration
}
val saveAnimator = ValueAnimator.ofFloat(binding.btnShare.alpha, 1f).apply {
addUpdateListener {
binding.btnShare.alpha = it.animatedValue as Float
binding.btnSave.alpha = it.animatedValue as Float
}
}
playTogether(radiusAnimator, saveAnimator)
duration = shortAnimationDuration
interpolator = DecelerateInterpolator()
start()
}
}
window?.let { window ->
window.navigationBarColor = Color.TRANSPARENT
window.decorView.fitsSystemWindows = true
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility
.rem(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility
.rem(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR)
}
}
}
override fun cancel() {
super.cancel()
thumbView.alpha = 1f
}
override fun dismiss() {
super.dismiss()
thumbView.alpha = 1f
}
private fun animateBack() {
val rect2 = Rect()
thumbView.getGlobalVisibleRect(rect2)
binding.mangaCoverFull.isClickable = false
binding.touchOutside.isClickable = false
val expandedImageView = binding.mangaCoverFull
val topInset = activity?.window?.decorView?.rootWindowInsets?.systemWindowInsetTop ?: 0
val leftInset = activity?.window?.decorView?.rootWindowInsets?.systemWindowInsetLeft ?: 0
val rightInset = activity?.window?.decorView?.rootWindowInsets?.systemWindowInsetRight ?: 0
expandedImageView.updateLayoutParams<ConstraintLayout.LayoutParams> {
height = thumbView.height
width = thumbView.width
topMargin = rect2.top - topInset
leftMargin = rect2.left - leftInset
rightMargin = rect2.right - rightInset
bottomMargin = rect2.bottom
horizontalBias = 0.0f
verticalBias = 0.0f
}
// Zoom out back to tc thumbnail
val transitionSet2 = TransitionSet()
val bound2 = ChangeBounds()
transitionSet2.addTransition(bound2)
val changeImageTransform2 = ChangeImageTransform()
transitionSet2.addTransition(changeImageTransform2)
transitionSet2.duration = shortAnimationDuration
TransitionManager.beginDelayedTransition(binding.root, transitionSet2)
if (Build.VERSION.SDK_INT >= 31) {
activity?.window?.decorView?.animateBlur(20f, 0.1f, 50, true)?.apply {
startDelay = shortAnimationDuration - 100
}?.start()
}
val attrs = window?.attributes
val ogDim = attrs?.dimAmount ?: 0.25f
// AnimationSet for backdrop because idk how to use TransitionSet
AnimatorSet().apply {
val radiusAnimator = ValueAnimator.ofFloat(fullRatio, ratio).apply {
addUpdateListener {
val value = it.animatedValue as Float
expandedImageView.shapeAppearanceModel =
expandedImageView.shapeAppearanceModel.toBuilder()
.setAllCorners(CornerFamily.ROUNDED, value)
.build()
}
}
val dimAnimator = ValueAnimator.ofFloat(ogDim, 0f).apply {
addUpdateListener {
window?.setDimAmount(it.animatedValue as Float)
}
}
val saveAnimator = ValueAnimator.ofFloat(binding.btnShare.alpha, 0f).apply {
addUpdateListener {
binding.btnShare.alpha = it.animatedValue as Float
binding.btnSave.alpha = it.animatedValue as Float
}
}
playTogether(radiusAnimator, dimAnimator, saveAnimator)
addListener(
onEnd = {
TransitionManager.endTransitions(binding.root)
thumbView.alpha = 1f
expandedImageView.post {
dismiss()
}
},
onCancel = {
TransitionManager.endTransitions(binding.root)
thumbView.alpha = 1f
expandedImageView.post {
dismiss()
}
}
)
interpolator = DecelerateInterpolator()
duration = shortAnimationDuration
}.start()
}
override fun onBackPressed() {
if (binding.mangaCoverFull.isClickable) {
animateBack()
}
}
}

View File

@ -1,9 +1,5 @@
package eu.kanade.tachiyomi.ui.manga
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.app.Activity
import android.content.ClipData
@ -12,9 +8,6 @@ import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Color
import android.graphics.Rect
import android.graphics.RenderEffect
import android.graphics.Shader
import android.graphics.drawable.BitmapDrawable
import android.os.Build
import android.os.Bundle
@ -25,7 +18,6 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.view.WindowInsets
import android.view.animation.DecelerateInterpolator
import android.view.inputmethod.InputMethodManager
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode
@ -37,10 +29,6 @@ import androidx.palette.graphics.Palette
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.transition.ChangeBounds
import androidx.transition.ChangeImageTransform
import androidx.transition.TransitionManager
import androidx.transition.TransitionSet
import coil.Coil
import coil.imageLoader
import coil.request.ImageRequest
@ -92,11 +80,9 @@ import eu.kanade.tachiyomi.util.isLocal
import eu.kanade.tachiyomi.util.moveCategories
import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.ThemeUtil
import eu.kanade.tachiyomi.util.system.contextCompatDrawable
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getPrefTheme
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.isInNightMode
import eu.kanade.tachiyomi.util.system.isOnline
import eu.kanade.tachiyomi.util.system.isTablet
import eu.kanade.tachiyomi.util.system.launchUI
@ -187,9 +173,6 @@ class MangaDetailsController :
private var actionMode: ActionMode? = null
// Hold a reference to the current animator, so that it can be canceled mid-way.
private var currentAnimator: Animator? = null
var headerHeight = 0
var fullCoverActive = false
@ -516,14 +499,6 @@ class MangaDetailsController :
activityBinding?.root?.clearFocus()
}
}
override fun handleBack(): Boolean {
if (binding.mangaCoverFull.visibility == View.VISIBLE) {
binding.mangaCoverFull.performClick()
return true
}
return super.handleBack()
}
//endregion
fun isNotOnline(showSnackbar: Boolean = true): Boolean {
@ -822,15 +797,6 @@ class MangaDetailsController :
//region action bar menu methods
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
if (fullCoverActive) {
colorToolbar(isColor = false)
activityBinding?.toolbar?.navigationIcon =
view?.context?.contextCompatDrawable(R.drawable.ic_arrow_back_24dp)?.apply {
setTint(Color.WHITE)
}
inflater.inflate(R.menu.manga_details_cover, menu)
return
}
colorToolbar(binding.recycler.canScrollVertically(-1))
activityBinding?.toolbar?.navigationIcon =
activityBinding?.toolbar?.navigationIcon?.mutate()?.apply {
@ -921,34 +887,36 @@ class MangaDetailsController :
R.id.download_next, R.id.download_next_5, R.id.download_custom, R.id.download_unread, R.id.download_all -> downloadChapters(
item.itemId
)
R.id.save -> {
if (presenter.saveCover()) {
activity?.toast(R.string.cover_saved)
} else {
activity?.toast(R.string.error_saving_cover)
}
}
R.id.share -> {
val cover = presenter.shareCover()
if (cover != null) {
val stream = cover.getUriCompat(activity!!)
val intent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_STREAM, stream)
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
clipData = ClipData.newRawUri(null, stream)
type = "image/*"
}
startActivity(Intent.createChooser(intent, activity?.getString(R.string.share)))
} else {
activity?.toast(R.string.error_sharing_cover)
}
}
else -> return super.onOptionsItemSelected(item)
}
return true
}
//endregion
fun saveCover() {
if (presenter.saveCover()) {
activity?.toast(R.string.cover_saved)
} else {
activity?.toast(R.string.error_saving_cover)
}
}
fun shareCover() {
val cover = presenter.shareCover()
if (cover != null) {
val stream = cover.getUriCompat(activity!!)
val intent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_STREAM, stream)
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
clipData = ClipData.newRawUri(null, stream)
type = "image/*"
}
startActivity(Intent.createChooser(intent, activity?.getString(R.string.share)))
} else {
activity?.toast(R.string.error_sharing_cover)
}
}
override fun prepareToShareManga() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val request = ImageRequest.Builder(activity!!).data(manga).target(
@ -1410,185 +1378,22 @@ class MangaDetailsController :
}
override fun zoomImageFromThumb(thumbView: View) {
// If there's an animation in progress, cancel it immediately and proceed with this one.
currentAnimator?.cancel()
// Load the high-resolution "zoomed-in" image.
val expandedImageView = binding.mangaCoverFull
val fullBackdrop = binding.fullBackdrop
// Hide the thumbnail and show the zoomed-in view. When the animation
// begins, it will position the zoomed-in view in the place of the
// thumbnail.
thumbView.alpha = 0f
expandedImageView.visibility = View.VISIBLE
fullBackdrop.visibility = View.VISIBLE
// Set the pivot point to 0 to match thumbnail
binding.swipeRefresh.isEnabled = false
val rect = Rect()
thumbView.getGlobalVisibleRect(rect)
expandedImageView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
height = thumbView.height
width = thumbView.width
topMargin = rect.top
leftMargin = rect.left
rightMargin = rect.right
bottomMargin = rect.bottom
}
expandedImageView.requestLayout()
val activity = activity as? MainActivity ?: return
val currColor = activity.drawerArrow?.color
if (!activity.isInNightMode()) {
activityBinding?.appBar?.context?.setTheme(R.style.ThemeOverlay_AppCompat_Dark_ActionBar)
val iconPrimary = Color.WHITE
activityBinding?.toolbar?.setTitleTextColor(iconPrimary)
activity.drawerArrow?.color = iconPrimary
activityBinding?.toolbar?.overflowIcon?.setTint(iconPrimary)
activity.window.decorView.systemUiVisibility =
activity.window.decorView.systemUiVisibility.rem(
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
)
}
if (fullCoverActive) return
fullCoverActive = true
activity.invalidateOptionsMenu()
expandedImageView.post {
val defMargin = 16.dpToPx
expandedImageView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
height = ViewGroup.LayoutParams.MATCH_PARENT
width = ViewGroup.LayoutParams.MATCH_PARENT
topMargin = defMargin + headerHeight
leftMargin = defMargin
rightMargin = defMargin
bottomMargin = defMargin + binding.recycler.paddingBottom
}
val shortAnimationDuration = (
resources?.getInteger(
android.R.integer.config_shortAnimTime
) ?: 0
).toLong()
// TransitionSet for the full cover because using animation for this SUCKS
val transitionSet = TransitionSet()
val bound = ChangeBounds()
transitionSet.addTransition(bound)
val changeImageTransform = ChangeImageTransform()
transitionSet.addTransition(changeImageTransform)
transitionSet.duration = shortAnimationDuration
TransitionManager.beginDelayedTransition(binding.frameLayout, transitionSet)
// AnimationSet for backdrop because idk how to use TransitionSet
currentAnimator = AnimatorSet().apply {
play(
ObjectAnimator.ofFloat(fullBackdrop, View.ALPHA, 0f, 0.5f)
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
binding.swipeRefresh.setRenderEffect(
RenderEffect.createBlurEffect(
15f,
15f,
Shader.TileMode.MIRROR
)
)
}
duration = shortAnimationDuration
interpolator = DecelerateInterpolator()
addListener(
object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
TransitionManager.endTransitions(binding.frameLayout)
currentAnimator = null
}
override fun onAnimationCancel(animation: Animator) {
TransitionManager.endTransitions(binding.frameLayout)
currentAnimator = null
}
}
)
start()
}
expandedImageView.setOnClickListener {
currentAnimator?.cancel()
fullCoverActive = false
activity.invalidateOptionsMenu()
val rect2 = Rect()
thumbView.getGlobalVisibleRect(rect2)
expandedImageView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
height = thumbView.height
width = thumbView.width
topMargin = rect2.top
leftMargin = rect2.left
rightMargin = rect2.right
bottomMargin = rect2.bottom
}
// Zoom out back to tc thumbnail
val transitionSet2 = TransitionSet()
val bound2 = ChangeBounds()
transitionSet2.addTransition(bound2)
val changeImageTransform2 = ChangeImageTransform()
transitionSet2.addTransition(changeImageTransform2)
transitionSet2.duration = shortAnimationDuration
TransitionManager.beginDelayedTransition(binding.frameLayout, transitionSet2)
// Animation to remove backdrop and hide the full cover
currentAnimator = AnimatorSet().apply {
play(ObjectAnimator.ofFloat(fullBackdrop, View.ALPHA, 0f))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
binding.swipeRefresh.setRenderEffect(null)
}
duration = shortAnimationDuration
interpolator = DecelerateInterpolator()
if (!activity.isInNightMode()) {
activityBinding?.appBar?.context?.setTheme(
activity.getPrefTheme(presenter.preferences).styleRes
)
val iconPrimary = currColor ?: Color.WHITE
activityBinding?.toolbar?.setTitleTextColor(iconPrimary)
activity.drawerArrow?.color = iconPrimary
activityBinding?.toolbar?.overflowIcon?.setTint(iconPrimary)
activity.window.decorView.systemUiVisibility =
activity.window.decorView.systemUiVisibility.or(
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
)
}
addListener(
object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
thumbView.alpha = 1f
expandedImageView.visibility = View.GONE
fullBackdrop.visibility = View.GONE
binding.swipeRefresh.isEnabled = true
currentAnimator = null
}
override fun onAnimationCancel(animation: Animator) {
thumbView.alpha = 1f
expandedImageView.visibility = View.GONE
fullBackdrop.visibility = View.GONE
binding.swipeRefresh.isEnabled = true
currentAnimator = null
}
}
)
start()
}
}
val expandedImageView = binding.mangaCoverFull
val fullCoverDialog = FullCoverDialog(
this,
expandedImageView.drawable,
thumbView
)
fullCoverDialog.setOnDismissListener {
fullCoverActive = false
}
fullCoverDialog.setOnCancelListener {
fullCoverActive = false
}
fullCoverDialog.show()
return
}
companion object {

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="1.00" android:color="?attr/colorPrimary" android:state_activated="true" />
<item android:alpha="0.38" android:color="?attr/colorOnSurface" android:state_activated="false" />
</selector>

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:background="@android:color/transparent"
tools:background="@color/gray_button"
xmlns:app="http://schemas.android.com/apk/res-auto">
<View
android:id="@+id/touch_outside"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="0dp"
android:layout_height="0dp"/>
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/manga_cover_full"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
tools:src="@mipmap/ic_launcher"
android:contentDescription="@string/cover_of_image"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/button_container" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/button_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintVertical_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginBottom="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_save"
style="@style/Widget.Tachiyomi.Button.ActionButton.White"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/btn_share"
app:layout_constraintStart_toStartOf="parent"
android:text="@string/save"
app:icon="@drawable/ic_save_24dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_share"
style="@style/Widget.Tachiyomi.Button.ActionButton.White"
app:layout_constraintStart_toEndOf="@id/btn_save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="@string/share"
app:icon="@drawable/ic_share_24dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -73,17 +73,6 @@
android:layout_height="match_parent"
app:fastScrollerBubbleEnabled="true" />
<View
android:id="@+id/full_backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0"
android:clickable="true"
android:focusable="true"
android:foreground="@color/md_black_1000"
android:visibility="invisible"
tools:background="@color/md_black_1000" />
<ImageView
android:id="@+id/manga_cover_full"
android:layout_width="match_parent"

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/save"
android:icon="@drawable/ic_save_24dp"
android:title="@string/save"
app:iconTint="@android:color/white"
app:showAsAction="ifRoom" />
<item
android:id="@+id/share"
android:icon="@drawable/ic_share_24dp"
android:title="@string/share"
app:iconTint="@android:color/white"
app:showAsAction="ifRoom" />
</menu>

View File

@ -197,6 +197,16 @@
<item name="android:windowExitAnimation">@anim/fade_out_short</item>
</style>
<style name="FullCoverDialogTheme" parent="BottomSheetDialogTheme">
<item name="android:windowAnimationStyle">@style/Theme.Widget.Animation.Static</item>
</style>
<style name="Theme.Widget.Animation.Static" parent="android:Animation">
<item name="android:windowEnterAnimation">@null</item>
<item name="android:windowExitAnimation">@null</item>
<item name="android:exitFadeDuration">0</item>
</style>
<style name="Theme.Widget.TextInputLayout.OutlinedBox.Dense" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense">
<item name="boxStrokeColor">@color/text_input_stroke</item>
<item name="hintTextColor">?colorAccent</item>
@ -235,6 +245,20 @@
<!--==============-->
<!--Widgets.Button-->
<!--==============-->
<style name="Widget.Tachiyomi.Button.ActionButton" parent="Widget.MaterialComponents.Button.TextButton.Icon">
<item name="iconGravity">top</item>
<item name="iconTint">@color/button_action_selector</item>
<item name="iconPadding">4dp</item>
<item name="android:textAllCaps">false</item>
<item name="android:textColor">@color/button_action_selector</item>
<item name="android:textSize">12sp</item>
</style>
<style name="Widget.Tachiyomi.Button.ActionButton.White">
<item name="iconTint">@color/md_white_1000</item>
<item name="android:textColor">@color/md_white_1000</item>
</style>
<style name="Theme.Widget.Button" parent="Widget.AppCompat.Button" />
<style name="Theme.Widget.Button.Colored" parent="Widget.MaterialComponents.Button">