Tablet manga view
This commit is contained in:
parent
685736b9ec
commit
7875f363a8
4 changed files with 135 additions and 28 deletions
|
@ -206,11 +206,17 @@ class MangaController :
|
||||||
override fun onViewCreated(view: View) {
|
override fun onViewCreated(view: View) {
|
||||||
super.onViewCreated(view)
|
super.onViewCreated(view)
|
||||||
|
|
||||||
binding.recycler.applyInsetter {
|
listOfNotNull(binding.fullRecycler, binding.infoRecycler, binding.chaptersRecycler)
|
||||||
type(navigationBars = true) {
|
.forEach {
|
||||||
padding()
|
it.applyInsetter {
|
||||||
|
type(navigationBars = true) {
|
||||||
|
padding()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it.layoutManager = LinearLayoutManager(view.context)
|
||||||
|
it.setHasFixedSize(true)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
binding.actionToolbar.applyInsetter {
|
binding.actionToolbar.applyInsetter {
|
||||||
type(navigationBars = true) {
|
type(navigationBars = true) {
|
||||||
margin(bottom = true)
|
margin(bottom = true)
|
||||||
|
@ -220,33 +226,42 @@ class MangaController :
|
||||||
if (manga == null || source == null) return
|
if (manga == null || source == null) return
|
||||||
|
|
||||||
// Init RecyclerView and adapter
|
// Init RecyclerView and adapter
|
||||||
mangaInfoAdapter = MangaInfoHeaderAdapter(this, fromSource)
|
mangaInfoAdapter = MangaInfoHeaderAdapter(this, fromSource, binding.infoRecycler != null)
|
||||||
chaptersHeaderAdapter = MangaChaptersHeaderAdapter(this)
|
chaptersHeaderAdapter = MangaChaptersHeaderAdapter(this)
|
||||||
chaptersAdapter = ChaptersAdapter(this, view.context)
|
chaptersAdapter = ChaptersAdapter(this, view.context)
|
||||||
|
|
||||||
binding.recycler.adapter = ConcatAdapter(mangaInfoAdapter, chaptersHeaderAdapter, chaptersAdapter)
|
// Phone layout
|
||||||
binding.recycler.layoutManager = LinearLayoutManager(view.context)
|
binding.fullRecycler?.let {
|
||||||
binding.recycler.setHasFixedSize(true)
|
it.adapter = ConcatAdapter(mangaInfoAdapter, chaptersHeaderAdapter, chaptersAdapter)
|
||||||
|
|
||||||
|
it.scrollEvents()
|
||||||
|
.onEach { updateToolbarTitleAlpha() }
|
||||||
|
.launchIn(viewScope)
|
||||||
|
}
|
||||||
|
// Tablet layout
|
||||||
|
binding.infoRecycler?.let {
|
||||||
|
it.adapter = mangaInfoAdapter
|
||||||
|
}
|
||||||
|
binding.chaptersRecycler?.let {
|
||||||
|
it.adapter = ConcatAdapter(chaptersHeaderAdapter, chaptersAdapter)
|
||||||
|
}
|
||||||
|
|
||||||
chaptersAdapter?.fastScroller = binding.fastScroller
|
chaptersAdapter?.fastScroller = binding.fastScroller
|
||||||
|
|
||||||
actionFabScrollListener = actionFab?.shrinkOnScroll(binding.recycler)
|
actionFabScrollListener = actionFab?.shrinkOnScroll(chaptersRecycler)
|
||||||
|
|
||||||
// Skips directly to chapters list if navigated to from the library
|
// Skips directly to chapters list if navigated to from the library
|
||||||
binding.recycler.post {
|
chaptersRecycler.post {
|
||||||
if (!fromSource && preferences.jumpToChapters()) {
|
if (!fromSource && preferences.jumpToChapters()) {
|
||||||
(binding.recycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(1, 0)
|
(chaptersRecycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(1, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delayed in case we need to jump to chapters
|
// Delayed in case we need to jump to chapters
|
||||||
binding.recycler.post {
|
binding.fullRecycler?.post {
|
||||||
updateToolbarTitleAlpha()
|
updateToolbarTitleAlpha()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.recycler.scrollEvents()
|
|
||||||
.onEach { updateToolbarTitleAlpha() }
|
|
||||||
.launchIn(viewScope)
|
|
||||||
|
|
||||||
binding.swipeRefresh.refreshes()
|
binding.swipeRefresh.refreshes()
|
||||||
.onEach {
|
.onEach {
|
||||||
fetchMangaInfoFromSource(manualFetch = true)
|
fetchMangaInfoFromSource(manualFetch = true)
|
||||||
|
@ -269,15 +284,19 @@ class MangaController :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateToolbarTitleAlpha(alpha: Int? = null) {
|
private fun updateToolbarTitleAlpha(alpha: Int? = null) {
|
||||||
|
if (binding.fullRecycler == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val calculatedAlpha = when {
|
val calculatedAlpha = when {
|
||||||
// Specific alpha provided
|
// Specific alpha provided
|
||||||
alpha != null -> alpha
|
alpha != null -> alpha
|
||||||
|
|
||||||
// First item isn't in view, full opacity
|
// First item isn't in view, full opacity
|
||||||
((binding.recycler.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() > 0) -> 255
|
((binding.fullRecycler!!.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() > 0) -> 255
|
||||||
|
|
||||||
// Based on scroll amount when first item is in view
|
// Based on scroll amount when first item is in view
|
||||||
else -> min(binding.recycler.computeVerticalScrollOffset(), 255)
|
else -> min(binding.fullRecycler!!.computeVerticalScrollOffset(), 255)
|
||||||
}
|
}
|
||||||
|
|
||||||
(activity as? MainActivity)?.binding?.toolbar?.setTitleTextColor(
|
(activity as? MainActivity)?.binding?.toolbar?.setTitleTextColor(
|
||||||
|
@ -321,7 +340,7 @@ class MangaController :
|
||||||
|
|
||||||
override fun cleanupFab(fab: ExtendedFloatingActionButton) {
|
override fun cleanupFab(fab: ExtendedFloatingActionButton) {
|
||||||
fab.setOnClickListener(null)
|
fab.setOnClickListener(null)
|
||||||
actionFabScrollListener?.let { binding.recycler.removeOnScrollListener(it) }
|
actionFabScrollListener?.let { binding.fullRecycler?.removeOnScrollListener(it) }
|
||||||
actionFab = null
|
actionFab = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1084,6 +1103,9 @@ class MangaController :
|
||||||
|
|
||||||
// Tracker sheet - end
|
// Tracker sheet - end
|
||||||
|
|
||||||
|
private val chaptersRecycler: RecyclerView
|
||||||
|
get() = binding.fullRecycler ?: binding.chaptersRecycler!!
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val FROM_SOURCE_EXTRA = "from_source"
|
const val FROM_SOURCE_EXTRA = "from_source"
|
||||||
const val MANGA_EXTRA = "manga"
|
const val MANGA_EXTRA = "manga"
|
||||||
|
|
|
@ -28,7 +28,8 @@ import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class MangaInfoHeaderAdapter(
|
class MangaInfoHeaderAdapter(
|
||||||
private val controller: MangaController,
|
private val controller: MangaController,
|
||||||
private val fromSource: Boolean
|
private val fromSource: Boolean,
|
||||||
|
private val isTablet: Boolean,
|
||||||
) :
|
) :
|
||||||
RecyclerView.Adapter<MangaInfoHeaderAdapter.HeaderViewHolder>() {
|
RecyclerView.Adapter<MangaInfoHeaderAdapter.HeaderViewHolder>() {
|
||||||
|
|
||||||
|
@ -194,10 +195,16 @@ class MangaInfoHeaderAdapter(
|
||||||
*/
|
*/
|
||||||
private fun setMangaInfo(manga: Manga, source: Source?) {
|
private fun setMangaInfo(manga: Manga, source: Source?) {
|
||||||
// Update full title TextView.
|
// Update full title TextView.
|
||||||
binding.mangaFullTitle.text = if (manga.title.isBlank()) {
|
with(binding.mangaFullTitle) {
|
||||||
view.context.getString(R.string.unknown)
|
if (isTablet) {
|
||||||
} else {
|
isVisible = false
|
||||||
manga.title
|
} else {
|
||||||
|
text = if (manga.title.isBlank()) {
|
||||||
|
view.context.getString(R.string.unknown)
|
||||||
|
} else {
|
||||||
|
manga.title
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update author TextView.
|
// Update author TextView.
|
||||||
|
@ -282,8 +289,9 @@ class MangaInfoHeaderAdapter(
|
||||||
.onEach { toggleMangaInfo() }
|
.onEach { toggleMangaInfo() }
|
||||||
.launchIn(controller.viewScope)
|
.launchIn(controller.viewScope)
|
||||||
|
|
||||||
// Expand manga info if navigated from source listing
|
// Expand manga info if navigated from source listing or explicitly set to
|
||||||
if (initialLoad && fromSource) {
|
// (e.g. on tablets)
|
||||||
|
if (initialLoad && (fromSource || isTablet)) {
|
||||||
toggleMangaInfo()
|
toggleMangaInfo()
|
||||||
initialLoad = false
|
initialLoad = false
|
||||||
}
|
}
|
||||||
|
|
78
app/src/main/res/layout-sw600dp/manga_controller.xml
Normal file
78
app/src/main/res/layout-sw600dp/manga_controller.xml
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout 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="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<eu.kanade.tachiyomi.widget.RevealAnimationView
|
||||||
|
android:id="@+id/reveal_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/colorAccent"
|
||||||
|
android:elevation="5dp"
|
||||||
|
android:visibility="invisible" />
|
||||||
|
|
||||||
|
<eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout
|
||||||
|
android:id="@+id/swipe_refresh"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/linear_recycler_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/info_recycler"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/chapters_recycler"
|
||||||
|
app:layout_constraintWidth_percent="0.4"
|
||||||
|
tools:itemCount="1"
|
||||||
|
tools:listitem="@layout/manga_info_header" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/chapters_recycler"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingBottom="@dimen/fab_list_padding"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/info_recycler"
|
||||||
|
tools:listitem="@layout/chapters_item" />
|
||||||
|
|
||||||
|
<eu.kanade.tachiyomi.widget.MaterialFastScroll
|
||||||
|
android:id="@+id/fast_scroller"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
app:fastScrollerBubbleEnabled="false"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<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_constraintStart_toStartOf="@+id/chapters_recycler"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/chapters_recycler"
|
||||||
|
app:layout_dodgeInsetEdges="bottom" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout>
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -18,11 +18,10 @@
|
||||||
android:id="@+id/swipe_refresh"
|
android:id="@+id/swipe_refresh"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_above="@+id/toolbar_bottom"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recycler"
|
android:id="@+id/full_recycler"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
|
|
Reference in a new issue