mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-21 20:47:03 -05:00
Action toolbar adjustments (#6353)
* Pair ActionToolbar with ActionMode This makes ActionToolbar an activity object that can be configured in the similar way as ActionMode * Remove action toolbar workaround now that it stays in activity layout 5924 * Set status bar color when action mode is active 6256 * Adjust fab show timing after action mode finished * Adjust action toolbar layout and animation Default corner size and use bottom sheet animation 6069 * Adjust action toolbar layout on large screen Right half of the screen
This commit is contained in:
parent
afc80d6a7c
commit
2ed01af723
14 changed files with 318 additions and 226 deletions
|
@ -7,7 +7,6 @@ import android.view.Menu
|
||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||||
|
@ -16,7 +15,6 @@ import com.google.android.material.tabs.TabLayout
|
||||||
import com.jakewharton.rxrelay.BehaviorRelay
|
import com.jakewharton.rxrelay.BehaviorRelay
|
||||||
import com.jakewharton.rxrelay.PublishRelay
|
import com.jakewharton.rxrelay.PublishRelay
|
||||||
import com.tfcporciuncula.flow.Preference
|
import com.tfcporciuncula.flow.Preference
|
||||||
import dev.chrisbanes.insetter.applyInsetter
|
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Category
|
import eu.kanade.tachiyomi.data.database.models.Category
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
|
@ -35,6 +33,7 @@ import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||||
import eu.kanade.tachiyomi.util.system.openInBrowser
|
import eu.kanade.tachiyomi.util.system.openInBrowser
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
|
import eu.kanade.tachiyomi.widget.ActionModeWithToolbar
|
||||||
import eu.kanade.tachiyomi.widget.EmptyView
|
import eu.kanade.tachiyomi.widget.EmptyView
|
||||||
import eu.kanade.tachiyomi.widget.materialdialogs.QuadStateTextView
|
import eu.kanade.tachiyomi.widget.materialdialogs.QuadStateTextView
|
||||||
import kotlinx.coroutines.flow.drop
|
import kotlinx.coroutines.flow.drop
|
||||||
|
@ -55,7 +54,7 @@ class LibraryController(
|
||||||
) : SearchableNucleusController<LibraryControllerBinding, LibraryPresenter>(bundle),
|
) : SearchableNucleusController<LibraryControllerBinding, LibraryPresenter>(bundle),
|
||||||
RootController,
|
RootController,
|
||||||
TabbedController,
|
TabbedController,
|
||||||
ActionMode.Callback,
|
ActionModeWithToolbar.Callback,
|
||||||
ChangeMangaCategoriesDialog.Listener,
|
ChangeMangaCategoriesDialog.Listener,
|
||||||
DeleteLibraryMangasDialog.Listener {
|
DeleteLibraryMangasDialog.Listener {
|
||||||
|
|
||||||
|
@ -67,7 +66,7 @@ class LibraryController(
|
||||||
/**
|
/**
|
||||||
* Action mode for selections.
|
* Action mode for selections.
|
||||||
*/
|
*/
|
||||||
private var actionMode: ActionMode? = null
|
private var actionMode: ActionModeWithToolbar? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently selected mangas.
|
* Currently selected mangas.
|
||||||
|
@ -170,12 +169,6 @@ class LibraryController(
|
||||||
override fun onViewCreated(view: View) {
|
override fun onViewCreated(view: View) {
|
||||||
super.onViewCreated(view)
|
super.onViewCreated(view)
|
||||||
|
|
||||||
binding.actionToolbar.applyInsetter {
|
|
||||||
type(navigationBars = true) {
|
|
||||||
margin(bottom = true, horizontal = true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter = LibraryAdapter(this)
|
adapter = LibraryAdapter(this)
|
||||||
binding.libraryPager.adapter = adapter
|
binding.libraryPager.adapter = adapter
|
||||||
binding.libraryPager.pageSelections()
|
binding.libraryPager.pageSelections()
|
||||||
|
@ -233,7 +226,6 @@ class LibraryController(
|
||||||
|
|
||||||
override fun onDestroyView(view: View) {
|
override fun onDestroyView(view: View) {
|
||||||
destroyActionModeIfNeeded()
|
destroyActionModeIfNeeded()
|
||||||
binding.actionToolbar.destroy()
|
|
||||||
adapter?.onDestroy()
|
adapter?.onDestroy()
|
||||||
adapter = null
|
adapter = null
|
||||||
settingsSheet = null
|
settingsSheet = null
|
||||||
|
@ -377,13 +369,10 @@ class LibraryController(
|
||||||
* Creates the action mode if it's not created already.
|
* Creates the action mode if it's not created already.
|
||||||
*/
|
*/
|
||||||
fun createActionModeIfNeeded() {
|
fun createActionModeIfNeeded() {
|
||||||
if (actionMode == null) {
|
val activity = activity
|
||||||
actionMode = (activity as AppCompatActivity).startSupportActionMode(this)
|
if (actionMode == null && activity is MainActivity) {
|
||||||
binding.actionToolbar.show(
|
actionMode = activity.startActionModeAndToolbar(this)
|
||||||
actionMode!!,
|
activity.showBottomNav(false)
|
||||||
R.menu.library_selection
|
|
||||||
) { onActionItemClicked(it!!) }
|
|
||||||
(activity as? MainActivity)?.showBottomNav(false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,6 +444,10 @@ class LibraryController(
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCreateActionToolbar(menuInflater: MenuInflater, menu: Menu) {
|
||||||
|
menuInflater.inflate(R.menu.library_selection, menu)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||||
val count = selectedMangas.size
|
val count = selectedMangas.size
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
|
@ -462,17 +455,17 @@ class LibraryController(
|
||||||
destroyActionModeIfNeeded()
|
destroyActionModeIfNeeded()
|
||||||
} else {
|
} else {
|
||||||
mode.title = count.toString()
|
mode.title = count.toString()
|
||||||
|
|
||||||
binding.actionToolbar.findItem(R.id.action_download_unread)?.isVisible = selectedMangas.any { it.source != LocalSource.ID }
|
|
||||||
}
|
}
|
||||||
return false
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareActionToolbar(toolbar: ActionModeWithToolbar, menu: Menu) {
|
||||||
|
if (selectedMangas.isEmpty()) return
|
||||||
|
toolbar.findToolbarItem(R.id.action_download_unread)?.isVisible =
|
||||||
|
selectedMangas.any { it.source != LocalSource.ID }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
||||||
return onActionItemClicked(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onActionItemClicked(item: MenuItem): Boolean {
|
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.action_move_to_category -> showChangeMangaCategoriesDialog()
|
R.id.action_move_to_category -> showChangeMangaCategoriesDialog()
|
||||||
R.id.action_download_unread -> downloadUnreadChapters()
|
R.id.action_download_unread -> downloadUnreadChapters()
|
||||||
|
@ -486,12 +479,11 @@ class LibraryController(
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
override fun onDestroyActionMode(mode: ActionMode) {
|
||||||
// Clear all the manga selections and notify child views.
|
// Clear all the manga selections and notify child views.
|
||||||
selectedMangas.clear()
|
selectedMangas.clear()
|
||||||
selectionRelay.call(LibrarySelectionEvent.Cleared())
|
selectionRelay.call(LibrarySelectionEvent.Cleared())
|
||||||
|
|
||||||
binding.actionToolbar.hide()
|
|
||||||
(activity as? MainActivity)?.showBottomNav(true)
|
(activity as? MainActivity)?.showBottomNav(true)
|
||||||
|
|
||||||
actionMode = null
|
actionMode = null
|
||||||
|
|
|
@ -12,13 +12,13 @@ import android.view.Window
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.core.animation.doOnEnd
|
import androidx.core.animation.doOnEnd
|
||||||
|
import androidx.core.graphics.ColorUtils
|
||||||
import androidx.core.splashscreen.SplashScreen
|
import androidx.core.splashscreen.SplashScreen
|
||||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updateLayoutParams
|
|
||||||
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
|
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
|
||||||
import androidx.interpolator.view.animation.LinearOutSlowInInterpolator
|
import androidx.interpolator.view.animation.LinearOutSlowInInterpolator
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
@ -27,7 +27,6 @@ import com.bluelinelabs.conductor.Conductor
|
||||||
import com.bluelinelabs.conductor.Controller
|
import com.bluelinelabs.conductor.Controller
|
||||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||||
import com.bluelinelabs.conductor.Router
|
import com.bluelinelabs.conductor.Router
|
||||||
import com.google.android.material.appbar.AppBarLayout
|
|
||||||
import com.google.android.material.navigation.NavigationBarView
|
import com.google.android.material.navigation.NavigationBarView
|
||||||
import com.google.android.material.transition.platform.MaterialContainerTransformSharedElementCallback
|
import com.google.android.material.transition.platform.MaterialContainerTransformSharedElementCallback
|
||||||
import dev.chrisbanes.insetter.applyInsetter
|
import dev.chrisbanes.insetter.applyInsetter
|
||||||
|
@ -63,10 +62,12 @@ import eu.kanade.tachiyomi.ui.setting.SettingsMainController
|
||||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
import eu.kanade.tachiyomi.util.lang.launchUI
|
||||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||||
|
import eu.kanade.tachiyomi.util.system.getThemeColor
|
||||||
import eu.kanade.tachiyomi.util.system.isTablet
|
import eu.kanade.tachiyomi.util.system.isTablet
|
||||||
import eu.kanade.tachiyomi.util.system.logcat
|
import eu.kanade.tachiyomi.util.system.logcat
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.view.setNavigationBarTransparentCompat
|
import eu.kanade.tachiyomi.util.view.setNavigationBarTransparentCompat
|
||||||
|
import eu.kanade.tachiyomi.widget.ActionModeWithToolbar
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.drop
|
import kotlinx.coroutines.flow.drop
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
@ -482,7 +483,11 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
|
||||||
tag = isTransparentWhenNotLifted
|
tag = isTransparentWhenNotLifted
|
||||||
isTransparentWhenNotLifted = false
|
isTransparentWhenNotLifted = false
|
||||||
}
|
}
|
||||||
setToolbarScrolls(false)
|
// Color taken from m3_appbar_background
|
||||||
|
window.statusBarColor = ColorUtils.compositeColors(
|
||||||
|
getColor(R.color.m3_appbar_overlay_color),
|
||||||
|
getThemeColor(R.attr.colorSurface)
|
||||||
|
)
|
||||||
super.onSupportActionModeStarted(mode)
|
super.onSupportActionModeStarted(mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,10 +496,15 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
|
||||||
isTransparentWhenNotLifted = (tag as? Boolean) ?: false
|
isTransparentWhenNotLifted = (tag as? Boolean) ?: false
|
||||||
tag = null
|
tag = null
|
||||||
}
|
}
|
||||||
setToolbarScrolls(true)
|
window.statusBarColor = getThemeColor(android.R.attr.statusBarColor)
|
||||||
super.onSupportActionModeFinished(mode)
|
super.onSupportActionModeFinished(mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun startActionModeAndToolbar(modeCallback: ActionModeWithToolbar.Callback): ActionModeWithToolbar {
|
||||||
|
binding.actionToolbar.start(modeCallback)
|
||||||
|
return binding.actionToolbar
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun resetExitConfirmation() {
|
private suspend fun resetExitConfirmation() {
|
||||||
isConfirmingExit = true
|
isConfirmingExit = true
|
||||||
val toast = toast(R.string.confirm_exit, Toast.LENGTH_LONG)
|
val toast = toast(R.string.confirm_exit, Toast.LENGTH_LONG)
|
||||||
|
@ -606,18 +616,6 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
|
||||||
binding.sideNav?.isVisible = visible
|
binding.sideNav?.isVisible = visible
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets toolbar CoordinatorLayout scroll flags
|
|
||||||
*/
|
|
||||||
private fun setToolbarScrolls(enabled: Boolean) = binding.toolbar.updateLayoutParams<AppBarLayout.LayoutParams> {
|
|
||||||
if (isTablet()) return@updateLayoutParams
|
|
||||||
scrollFlags = if (enabled) {
|
|
||||||
AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL or AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val nav: NavigationBarView
|
private val nav: NavigationBarView
|
||||||
get() = binding.bottomNav ?: binding.sideNav!!
|
get() = binding.bottomNav ?: binding.sideNav!!
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.annotation.FloatRange
|
import androidx.annotation.FloatRange
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
|
@ -91,6 +90,7 @@ 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.shrinkOnScroll
|
import eu.kanade.tachiyomi.util.view.shrinkOnScroll
|
||||||
import eu.kanade.tachiyomi.util.view.snack
|
import eu.kanade.tachiyomi.util.view.snack
|
||||||
|
import eu.kanade.tachiyomi.widget.ActionModeWithToolbar
|
||||||
import eu.kanade.tachiyomi.widget.materialdialogs.QuadStateTextView
|
import eu.kanade.tachiyomi.widget.materialdialogs.QuadStateTextView
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
@ -106,7 +106,7 @@ import kotlin.math.min
|
||||||
class MangaController :
|
class MangaController :
|
||||||
NucleusController<MangaControllerBinding, MangaPresenter>,
|
NucleusController<MangaControllerBinding, MangaPresenter>,
|
||||||
FabController,
|
FabController,
|
||||||
ActionMode.Callback,
|
ActionModeWithToolbar.Callback,
|
||||||
FlexibleAdapter.OnItemClickListener,
|
FlexibleAdapter.OnItemClickListener,
|
||||||
FlexibleAdapter.OnItemLongClickListener,
|
FlexibleAdapter.OnItemLongClickListener,
|
||||||
BaseChaptersAdapter.OnChapterClickListener,
|
BaseChaptersAdapter.OnChapterClickListener,
|
||||||
|
@ -161,7 +161,7 @@ class MangaController :
|
||||||
/**
|
/**
|
||||||
* Action mode for multiple selection.
|
* Action mode for multiple selection.
|
||||||
*/
|
*/
|
||||||
private var actionMode: ActionMode? = null
|
private var actionMode: ActionModeWithToolbar? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selected items. Used to restore selections after a rotation.
|
* Selected items. Used to restore selections after a rotation.
|
||||||
|
@ -238,11 +238,6 @@ class MangaController :
|
||||||
it.layoutManager = LinearLayoutManager(view.context)
|
it.layoutManager = LinearLayoutManager(view.context)
|
||||||
it.setHasFixedSize(true)
|
it.setHasFixedSize(true)
|
||||||
}
|
}
|
||||||
binding.actionToolbar.applyInsetter {
|
|
||||||
type(navigationBars = true) {
|
|
||||||
margin(bottom = true, horizontal = true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (manga == null || source == null) return
|
if (manga == null || source == null) return
|
||||||
|
|
||||||
|
@ -382,16 +377,19 @@ class MangaController :
|
||||||
val context = view?.context ?: return
|
val context = view?.context ?: return
|
||||||
val adapter = chaptersAdapter ?: return
|
val adapter = chaptersAdapter ?: return
|
||||||
val fab = actionFab ?: return
|
val fab = actionFab ?: return
|
||||||
fab.isVisible = adapter.items.any { !it.read }
|
|
||||||
if (adapter.items.any { it.read }) {
|
if (adapter.items.any { it.read }) {
|
||||||
fab.text = context.getString(R.string.action_resume)
|
fab.text = context.getString(R.string.action_resume)
|
||||||
}
|
}
|
||||||
|
if (adapter.items.any { !it.read }) {
|
||||||
|
fab.show()
|
||||||
|
} else {
|
||||||
|
fab.hide()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView(view: View) {
|
override fun onDestroyView(view: View) {
|
||||||
recyclerViewUpdatesToolbarTitleAlpha(false)
|
recyclerViewUpdatesToolbarTitleAlpha(false)
|
||||||
destroyActionModeIfNeeded()
|
destroyActionModeIfNeeded()
|
||||||
binding.actionToolbar.destroy()
|
|
||||||
mangaInfoAdapter = null
|
mangaInfoAdapter = null
|
||||||
chaptersHeaderAdapter = null
|
chaptersHeaderAdapter = null
|
||||||
chaptersAdapter = null
|
chaptersAdapter = null
|
||||||
|
@ -978,11 +976,7 @@ class MangaController :
|
||||||
|
|
||||||
private fun createActionModeIfNeeded() {
|
private fun createActionModeIfNeeded() {
|
||||||
if (actionMode == null) {
|
if (actionMode == null) {
|
||||||
actionMode = (activity as? AppCompatActivity)?.startSupportActionMode(this)
|
actionMode = (activity as MainActivity).startActionModeAndToolbar(this)
|
||||||
binding.actionToolbar.show(
|
|
||||||
actionMode!!,
|
|
||||||
R.menu.chapter_selection
|
|
||||||
) { onActionItemClicked(it!!) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -998,6 +992,10 @@ class MangaController :
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCreateActionToolbar(menuInflater: MenuInflater, menu: Menu) {
|
||||||
|
menuInflater.inflate(R.menu.chapter_selection, menu)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||||
val count = chaptersAdapter?.selectedItemCount ?: 0
|
val count = chaptersAdapter?.selectedItemCount ?: 0
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
|
@ -1006,25 +1004,24 @@ class MangaController :
|
||||||
} else {
|
} else {
|
||||||
mode.title = count.toString()
|
mode.title = count.toString()
|
||||||
|
|
||||||
val chapters = getSelectedChapters()
|
|
||||||
binding.actionToolbar.findItem(R.id.action_download)?.isVisible = !isLocalSource && chapters.any { !it.isDownloaded }
|
|
||||||
binding.actionToolbar.findItem(R.id.action_delete)?.isVisible = !isLocalSource && chapters.any { it.isDownloaded }
|
|
||||||
binding.actionToolbar.findItem(R.id.action_bookmark)?.isVisible = chapters.any { !it.chapter.bookmark }
|
|
||||||
binding.actionToolbar.findItem(R.id.action_remove_bookmark)?.isVisible = chapters.all { it.chapter.bookmark }
|
|
||||||
binding.actionToolbar.findItem(R.id.action_mark_as_read)?.isVisible = chapters.any { !it.chapter.read }
|
|
||||||
binding.actionToolbar.findItem(R.id.action_mark_as_unread)?.isVisible = chapters.all { it.chapter.read }
|
|
||||||
|
|
||||||
// Hide FAB to avoid interfering with the bottom action toolbar
|
// Hide FAB to avoid interfering with the bottom action toolbar
|
||||||
actionFab?.isVisible = false
|
actionFab?.hide()
|
||||||
}
|
}
|
||||||
return false
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareActionToolbar(toolbar: ActionModeWithToolbar, menu: Menu) {
|
||||||
|
val chapters = getSelectedChapters()
|
||||||
|
if (chapters.isEmpty()) return
|
||||||
|
toolbar.findToolbarItem(R.id.action_download)?.isVisible = !isLocalSource && chapters.any { !it.isDownloaded }
|
||||||
|
toolbar.findToolbarItem(R.id.action_delete)?.isVisible = !isLocalSource && chapters.any { it.isDownloaded }
|
||||||
|
toolbar.findToolbarItem(R.id.action_bookmark)?.isVisible = chapters.any { !it.chapter.bookmark }
|
||||||
|
toolbar.findToolbarItem(R.id.action_remove_bookmark)?.isVisible = chapters.all { it.chapter.bookmark }
|
||||||
|
toolbar.findToolbarItem(R.id.action_mark_as_read)?.isVisible = chapters.any { !it.chapter.read }
|
||||||
|
toolbar.findToolbarItem(R.id.action_mark_as_unread)?.isVisible = chapters.all { it.chapter.read }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
||||||
return onActionItemClicked(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onActionItemClicked(item: MenuItem): Boolean {
|
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.action_select_all -> selectAll()
|
R.id.action_select_all -> selectAll()
|
||||||
R.id.action_select_inverse -> selectInverse()
|
R.id.action_select_inverse -> selectInverse()
|
||||||
|
@ -1041,11 +1038,13 @@ class MangaController :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyActionMode(mode: ActionMode) {
|
override fun onDestroyActionMode(mode: ActionMode) {
|
||||||
binding.actionToolbar.hide()
|
|
||||||
chaptersAdapter?.mode = SelectableAdapter.Mode.SINGLE
|
chaptersAdapter?.mode = SelectableAdapter.Mode.SINGLE
|
||||||
chaptersAdapter?.clearSelection()
|
chaptersAdapter?.clearSelection()
|
||||||
selectedChapters.clear()
|
selectedChapters.clear()
|
||||||
actionMode = null
|
actionMode = null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyActionToolbar() {
|
||||||
updateFabVisibility()
|
updateFabVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import android.view.Menu
|
||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import dev.chrisbanes.insetter.applyInsetter
|
import dev.chrisbanes.insetter.applyInsetter
|
||||||
|
@ -29,6 +28,7 @@ import eu.kanade.tachiyomi.util.system.logcat
|
||||||
import eu.kanade.tachiyomi.util.system.notificationManager
|
import eu.kanade.tachiyomi.util.system.notificationManager
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.view.onAnimationsFinished
|
import eu.kanade.tachiyomi.util.view.onAnimationsFinished
|
||||||
|
import eu.kanade.tachiyomi.widget.ActionModeWithToolbar
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
|
@ -41,7 +41,7 @@ import reactivecircus.flowbinding.swiperefreshlayout.refreshes
|
||||||
class UpdatesController :
|
class UpdatesController :
|
||||||
NucleusController<UpdatesControllerBinding, UpdatesPresenter>(),
|
NucleusController<UpdatesControllerBinding, UpdatesPresenter>(),
|
||||||
RootController,
|
RootController,
|
||||||
ActionMode.Callback,
|
ActionModeWithToolbar.Callback,
|
||||||
FlexibleAdapter.OnItemClickListener,
|
FlexibleAdapter.OnItemClickListener,
|
||||||
FlexibleAdapter.OnItemLongClickListener,
|
FlexibleAdapter.OnItemLongClickListener,
|
||||||
FlexibleAdapter.OnUpdateListener,
|
FlexibleAdapter.OnUpdateListener,
|
||||||
|
@ -52,7 +52,7 @@ class UpdatesController :
|
||||||
/**
|
/**
|
||||||
* Action mode for multiple selection.
|
* Action mode for multiple selection.
|
||||||
*/
|
*/
|
||||||
private var actionMode: ActionMode? = null
|
private var actionMode: ActionModeWithToolbar? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter containing the recent chapters.
|
* Adapter containing the recent chapters.
|
||||||
|
@ -81,11 +81,6 @@ class UpdatesController :
|
||||||
padding()
|
padding()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.actionToolbar.applyInsetter {
|
|
||||||
type(navigationBars = true) {
|
|
||||||
margin(bottom = true, horizontal = true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
view.context.notificationManager.cancel(Notifications.ID_NEW_CHAPTERS)
|
view.context.notificationManager.cancel(Notifications.ID_NEW_CHAPTERS)
|
||||||
|
|
||||||
|
@ -118,7 +113,6 @@ class UpdatesController :
|
||||||
|
|
||||||
override fun onDestroyView(view: View) {
|
override fun onDestroyView(view: View) {
|
||||||
destroyActionModeIfNeeded()
|
destroyActionModeIfNeeded()
|
||||||
binding.actionToolbar.destroy()
|
|
||||||
adapter = null
|
adapter = null
|
||||||
super.onDestroyView(view)
|
super.onDestroyView(view)
|
||||||
}
|
}
|
||||||
|
@ -175,15 +169,11 @@ class UpdatesController :
|
||||||
* @param position position of clicked item
|
* @param position position of clicked item
|
||||||
*/
|
*/
|
||||||
override fun onItemLongClick(position: Int) {
|
override fun onItemLongClick(position: Int) {
|
||||||
if (actionMode == null) {
|
val activity = activity
|
||||||
actionMode = (activity as AppCompatActivity).startSupportActionMode(this)
|
if (actionMode == null && activity is MainActivity) {
|
||||||
binding.actionToolbar.show(
|
actionMode = activity.startActionModeAndToolbar(this)
|
||||||
actionMode!!,
|
activity.showBottomNav(false)
|
||||||
R.menu.updates_chapter_selection
|
|
||||||
) { onActionItemClicked(it!!) }
|
|
||||||
(activity as? MainActivity)?.showBottomNav(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleSelection(position)
|
toggleSelection(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,6 +331,10 @@ class UpdatesController :
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCreateActionToolbar(menuInflater: MenuInflater, menu: Menu) {
|
||||||
|
menuInflater.inflate(R.menu.updates_chapter_selection, menu)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||||
val count = adapter?.selectedItemCount ?: 0
|
val count = adapter?.selectedItemCount ?: 0
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
|
@ -348,17 +342,19 @@ class UpdatesController :
|
||||||
destroyActionModeIfNeeded()
|
destroyActionModeIfNeeded()
|
||||||
} else {
|
} else {
|
||||||
mode.title = count.toString()
|
mode.title = count.toString()
|
||||||
|
|
||||||
val chapters = getSelectedChapters()
|
|
||||||
binding.actionToolbar.findItem(R.id.action_download)?.isVisible = chapters.any { !it.isDownloaded }
|
|
||||||
binding.actionToolbar.findItem(R.id.action_delete)?.isVisible = chapters.any { it.isDownloaded }
|
|
||||||
binding.actionToolbar.findItem(R.id.action_bookmark)?.isVisible = chapters.any { !it.bookmark }
|
|
||||||
binding.actionToolbar.findItem(R.id.action_remove_bookmark)?.isVisible = chapters.all { it.bookmark }
|
|
||||||
binding.actionToolbar.findItem(R.id.action_mark_as_read)?.isVisible = chapters.any { !it.chapter.read }
|
|
||||||
binding.actionToolbar.findItem(R.id.action_mark_as_unread)?.isVisible = chapters.all { it.chapter.read }
|
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
override fun onPrepareActionToolbar(toolbar: ActionModeWithToolbar, menu: Menu) {
|
||||||
|
val chapters = getSelectedChapters()
|
||||||
|
if (chapters.isEmpty()) return
|
||||||
|
toolbar.findToolbarItem(R.id.action_download)?.isVisible = chapters.any { !it.isDownloaded }
|
||||||
|
toolbar.findToolbarItem(R.id.action_delete)?.isVisible = chapters.any { it.isDownloaded }
|
||||||
|
toolbar.findToolbarItem(R.id.action_bookmark)?.isVisible = chapters.any { !it.bookmark }
|
||||||
|
toolbar.findToolbarItem(R.id.action_remove_bookmark)?.isVisible = chapters.all { it.bookmark }
|
||||||
|
toolbar.findToolbarItem(R.id.action_mark_as_read)?.isVisible = chapters.any { !it.chapter.read }
|
||||||
|
toolbar.findToolbarItem(R.id.action_mark_as_unread)?.isVisible = chapters.all { it.chapter.read }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -391,11 +387,10 @@ class UpdatesController :
|
||||||
* Called when ActionMode destroyed
|
* Called when ActionMode destroyed
|
||||||
* @param mode the ActionMode object
|
* @param mode the ActionMode object
|
||||||
*/
|
*/
|
||||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
override fun onDestroyActionMode(mode: ActionMode) {
|
||||||
adapter?.mode = SelectableAdapter.Mode.IDLE
|
adapter?.mode = SelectableAdapter.Mode.IDLE
|
||||||
adapter?.clearSelection()
|
adapter?.clearSelection()
|
||||||
|
|
||||||
binding.actionToolbar.hide()
|
|
||||||
(activity as? MainActivity)?.showBottomNav(true)
|
(activity as? MainActivity)?.showBottomNav(true)
|
||||||
|
|
||||||
actionMode = null
|
actionMode = null
|
||||||
|
|
|
@ -0,0 +1,168 @@
|
||||||
|
package eu.kanade.tachiyomi.widget
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.animation.Animation
|
||||||
|
import android.view.animation.AnimationUtils
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import androidx.annotation.IdRes
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.appcompat.view.ActionMode
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import dev.chrisbanes.insetter.applyInsetter
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.databinding.ActionToolbarBinding
|
||||||
|
import eu.kanade.tachiyomi.util.system.applySystemAnimatorScale
|
||||||
|
import eu.kanade.tachiyomi.widget.listener.SimpleAnimationListener
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A toolbar holding only menu items. This view is supposed to be paired with [AppCompatActivity]'s [ActionMode].
|
||||||
|
*
|
||||||
|
* @see Callback
|
||||||
|
*/
|
||||||
|
class ActionModeWithToolbar @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||||
|
FrameLayout(context, attrs) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
clipToPadding = false
|
||||||
|
applyInsetter {
|
||||||
|
type(navigationBars = true) {
|
||||||
|
padding(bottom = true, horizontal = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val binding = ActionToolbarBinding.inflate(LayoutInflater.from(context), this, true)
|
||||||
|
|
||||||
|
private var callback: Callback? = null
|
||||||
|
|
||||||
|
private var actionMode: ActionMode? = null
|
||||||
|
private val actionModeCallback = object : ActionMode.Callback {
|
||||||
|
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||||
|
callback?.onCreateActionToolbar(mode.menuInflater, binding.menu.menu)
|
||||||
|
binding.menu.setOnMenuItemClickListener { onActionItemClicked(mode, it) }
|
||||||
|
binding.root.isVisible = true
|
||||||
|
val bottomAnimation = AnimationUtils.loadAnimation(context, R.anim.bottom_sheet_slide_in)
|
||||||
|
bottomAnimation.applySystemAnimatorScale(context)
|
||||||
|
binding.root.startAnimation(bottomAnimation)
|
||||||
|
|
||||||
|
return callback?.onCreateActionMode(mode, menu) ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||||
|
callback?.onPrepareActionToolbar(this@ActionModeWithToolbar, binding.menu.menu)
|
||||||
|
return callback?.onPrepareActionMode(mode, menu) ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
||||||
|
return callback?.onActionItemClicked(mode, item) ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyActionMode(mode: ActionMode) {
|
||||||
|
callback?.onDestroyActionMode(mode)
|
||||||
|
|
||||||
|
val bottomAnimation = AnimationUtils.loadAnimation(context, R.anim.bottom_sheet_slide_out).apply {
|
||||||
|
applySystemAnimatorScale(context)
|
||||||
|
setAnimationListener(
|
||||||
|
object : SimpleAnimationListener() {
|
||||||
|
override fun onAnimationEnd(animation: Animation) {
|
||||||
|
binding.root.isVisible = false
|
||||||
|
binding.menu.menu.clear()
|
||||||
|
binding.menu.setOnMenuItemClickListener(null)
|
||||||
|
|
||||||
|
callback?.onDestroyActionToolbar()
|
||||||
|
callback = null
|
||||||
|
actionMode = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
binding.root.startAnimation(bottomAnimation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun start(callback: Callback) {
|
||||||
|
val context = context
|
||||||
|
if (context !is AppCompatActivity) {
|
||||||
|
throw IllegalStateException("AppCompatActivity is needed to start this view")
|
||||||
|
}
|
||||||
|
if (actionMode == null) {
|
||||||
|
this.callback = callback
|
||||||
|
actionMode = context.startSupportActionMode(actionModeCallback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun finish() {
|
||||||
|
actionMode?.finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a menu item if found.
|
||||||
|
*/
|
||||||
|
fun findToolbarItem(@IdRes itemId: Int): MenuItem? {
|
||||||
|
return binding.menu.menu.findItem(itemId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun invalidate() {
|
||||||
|
super.invalidate()
|
||||||
|
actionMode?.invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Callback {
|
||||||
|
/**
|
||||||
|
* Called when action mode is first created. The menu supplied will be used to
|
||||||
|
* generate action buttons for the action mode.
|
||||||
|
*
|
||||||
|
* @param mode ActionMode being created
|
||||||
|
* @param menu Menu used to populate action buttons
|
||||||
|
* @return true if the action mode should be created, false if entering this
|
||||||
|
* mode should be aborted.
|
||||||
|
*/
|
||||||
|
fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [onCreateActionMode] but for the bottom toolbar
|
||||||
|
*/
|
||||||
|
fun onCreateActionToolbar(menuInflater: MenuInflater, menu: Menu)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to refresh an action mode's action menu whenever it is invalidated.
|
||||||
|
*
|
||||||
|
* @param mode ActionMode being prepared
|
||||||
|
* @param menu Menu used to populate action buttons
|
||||||
|
* @return true if the menu or action mode was updated, false otherwise.
|
||||||
|
*/
|
||||||
|
fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [onPrepareActionMode] but for the bottom toolbar
|
||||||
|
*/
|
||||||
|
fun onPrepareActionToolbar(toolbar: ActionModeWithToolbar, menu: Menu)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to report a user click on an action button.
|
||||||
|
*
|
||||||
|
* @param mode The current ActionMode
|
||||||
|
* @param item The item that was clicked
|
||||||
|
* @return true if this callback handled the event, false if the standard MenuItem
|
||||||
|
* invocation should continue.
|
||||||
|
*/
|
||||||
|
fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an action mode is about to be exited and destroyed.
|
||||||
|
*
|
||||||
|
* @param mode The current ActionMode being destroyed
|
||||||
|
*/
|
||||||
|
fun onDestroyActionMode(mode: ActionMode)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the action toolbar is finished exiting
|
||||||
|
*/
|
||||||
|
fun onDestroyActionToolbar() {}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,73 +0,0 @@
|
||||||
package eu.kanade.tachiyomi.widget
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.MenuItem
|
|
||||||
import android.view.animation.Animation
|
|
||||||
import android.view.animation.AnimationUtils
|
|
||||||
import android.widget.FrameLayout
|
|
||||||
import androidx.annotation.IdRes
|
|
||||||
import androidx.annotation.MenuRes
|
|
||||||
import androidx.appcompat.view.ActionMode
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import eu.kanade.tachiyomi.R
|
|
||||||
import eu.kanade.tachiyomi.databinding.ActionToolbarBinding
|
|
||||||
import eu.kanade.tachiyomi.util.system.applySystemAnimatorScale
|
|
||||||
import eu.kanade.tachiyomi.widget.listener.SimpleAnimationListener
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A toolbar holding only menu items.
|
|
||||||
*/
|
|
||||||
class ActionToolbar @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
|
||||||
FrameLayout(context, attrs) {
|
|
||||||
|
|
||||||
private val binding = ActionToolbarBinding.inflate(LayoutInflater.from(context), this, true)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove menu items and remove listener.
|
|
||||||
*/
|
|
||||||
fun destroy() {
|
|
||||||
binding.menu.menu.clear()
|
|
||||||
binding.menu.setOnMenuItemClickListener(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a menu item if found.
|
|
||||||
*/
|
|
||||||
fun findItem(@IdRes itemId: Int): MenuItem? {
|
|
||||||
return binding.menu.menu.findItem(itemId)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the menu toolbar using the provided ActionMode's context to inflate the items.
|
|
||||||
*/
|
|
||||||
fun show(mode: ActionMode, @MenuRes menuRes: Int, listener: (item: MenuItem?) -> Boolean) {
|
|
||||||
// Avoid re-inflating the menu
|
|
||||||
if (binding.menu.menu.size() == 0) {
|
|
||||||
mode.menuInflater.inflate(menuRes, binding.menu.menu)
|
|
||||||
binding.menu.setOnMenuItemClickListener { listener(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.actionToolbar.isVisible = true
|
|
||||||
val bottomAnimation = AnimationUtils.loadAnimation(context, R.anim.enter_from_bottom)
|
|
||||||
bottomAnimation.applySystemAnimatorScale(context)
|
|
||||||
binding.actionToolbar.startAnimation(bottomAnimation)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hide the menu toolbar.
|
|
||||||
*/
|
|
||||||
fun hide() {
|
|
||||||
val bottomAnimation = AnimationUtils.loadAnimation(context, R.anim.exit_to_bottom)
|
|
||||||
bottomAnimation.applySystemAnimatorScale(context)
|
|
||||||
bottomAnimation.setAnimationListener(
|
|
||||||
object : SimpleAnimationListener() {
|
|
||||||
override fun onAnimationEnd(animation: Animation) {
|
|
||||||
binding.actionToolbar.isVisible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
binding.actionToolbar.startAnimation(bottomAnimation)
|
|
||||||
}
|
|
||||||
}
|
|
40
app/src/main/res/layout-sw720dp/action_toolbar.xml
Normal file
40
app/src/main/res/layout-sw720dp/action_toolbar.xml
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="12dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="1.0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintWidth_default="percent"
|
||||||
|
app:layout_constraintWidth_percent=".5">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
app:contentInsetEnd="8dp"
|
||||||
|
app:contentInsetStart="8dp">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.ActionMenuView
|
||||||
|
android:id="@+id/menu"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center" />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.MaterialToolbar>
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -99,6 +99,12 @@
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<eu.kanade.tachiyomi.widget.ActionModeWithToolbar
|
||||||
|
android:id="@+id/action_toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom" />
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/fab_layout"
|
android:id="@+id/fab_layout"
|
||||||
layout="@layout/main_activity_fab" />
|
layout="@layout/main_activity_fab" />
|
||||||
|
|
|
@ -43,16 +43,6 @@
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:listitem="@layout/chapters_item" />
|
tools:listitem="@layout/chapters_item" />
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.widget.ActionToolbar
|
|
||||||
android:id="@+id/action_toolbar"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="@+id/chapters_recycler"
|
|
||||||
app:layout_constraintStart_toStartOf="@+id/chapters_recycler"
|
|
||||||
app:layout_dodgeInsetEdges="bottom" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout>
|
</eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout>
|
||||||
|
|
|
@ -1,35 +1,27 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/action_toolbar"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="12dp"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:padding="8dp"
|
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible">
|
tools:visibility="visible">
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="?attr/actionBarSize"
|
||||||
app:cardCornerRadius="@dimen/dialog_radius">
|
android:layout_gravity="bottom"
|
||||||
|
app:contentInsetEnd="8dp"
|
||||||
|
app:contentInsetStart="8dp">
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<androidx.appcompat.widget.ActionMenuView
|
||||||
|
android:id="@+id/menu"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="center" />
|
||||||
app:contentInsetEnd="8dp"
|
|
||||||
app:contentInsetStart="8dp">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.ActionMenuView
|
</com.google.android.material.appbar.MaterialToolbar>
|
||||||
android:id="@+id/menu"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_gravity="center" />
|
|
||||||
|
|
||||||
</com.google.android.material.appbar.MaterialToolbar>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
|
@ -27,13 +27,6 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.widget.ActionToolbar
|
|
||||||
android:id="@+id/action_toolbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
app:layout_dodgeInsetEdges="bottom" />
|
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.widget.EmptyView
|
<eu.kanade.tachiyomi.widget.EmptyView
|
||||||
android:id="@+id/empty_view"
|
android:id="@+id/empty_view"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -74,6 +74,12 @@
|
||||||
android:id="@+id/fab_layout"
|
android:id="@+id/fab_layout"
|
||||||
layout="@layout/main_activity_fab" />
|
layout="@layout/main_activity_fab" />
|
||||||
|
|
||||||
|
<eu.kanade.tachiyomi.widget.ActionModeWithToolbar
|
||||||
|
android:id="@+id/action_toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom" />
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.widget.TachiyomiBottomNavigationView
|
<eu.kanade.tachiyomi.widget.TachiyomiBottomNavigationView
|
||||||
android:id="@+id/bottom_nav"
|
android:id="@+id/bottom_nav"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -33,11 +33,4 @@
|
||||||
app:fastScrollerBubbleEnabled="false"
|
app:fastScrollerBubbleEnabled="false"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.widget.ActionToolbar
|
|
||||||
android:id="@+id/action_toolbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
app:layout_dodgeInsetEdges="bottom" />
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
|
@ -27,13 +27,6 @@
|
||||||
app:fastScrollerBubbleEnabled="false"
|
app:fastScrollerBubbleEnabled="false"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.widget.ActionToolbar
|
|
||||||
android:id="@+id/action_toolbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
app:layout_dodgeInsetEdges="bottom" />
|
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.widget.EmptyView
|
<eu.kanade.tachiyomi.widget.EmptyView
|
||||||
android:id="@+id/empty_view"
|
android:id="@+id/empty_view"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
Loading…
Reference in a new issue