Tablet UI for manga details

It returns for some reason... even I'm trying to figure out why

enjoy my 8 tablet users

Also kinda fix the view scrolling down a bit when tapping on the expanded summary when the summary is extremely long
This commit is contained in:
Jays2Kings 2021-05-08 22:48:43 -04:00
parent 0c2262ccba
commit 4999db33f4
7 changed files with 243 additions and 89 deletions

View File

@ -11,6 +11,7 @@ import android.content.ClipData
import android.content.ClipboardManager import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.res.Configuration
import android.graphics.Color import android.graphics.Color
import android.graphics.Rect import android.graphics.Rect
import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.BitmapDrawable
@ -30,6 +31,7 @@ import androidx.appcompat.view.ActionMode
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.core.graphics.ColorUtils import androidx.core.graphics.ColorUtils
import androidx.core.view.isVisible
import androidx.palette.graphics.Palette import androidx.palette.graphics.Palette
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@ -95,15 +97,18 @@ import eu.kanade.tachiyomi.util.system.getPrefTheme
import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.isInNightMode import eu.kanade.tachiyomi.util.system.isInNightMode
import eu.kanade.tachiyomi.util.system.isOnline import eu.kanade.tachiyomi.util.system.isOnline
import eu.kanade.tachiyomi.util.system.isTablet
import eu.kanade.tachiyomi.util.system.launchUI import eu.kanade.tachiyomi.util.system.launchUI
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.activityBinding import eu.kanade.tachiyomi.util.view.activityBinding
import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsets
import eu.kanade.tachiyomi.util.view.getText import eu.kanade.tachiyomi.util.view.getText
import eu.kanade.tachiyomi.util.view.requestPermissionsSafe import eu.kanade.tachiyomi.util.view.requestPermissionsSafe
import eu.kanade.tachiyomi.util.view.scrollViewWith import eu.kanade.tachiyomi.util.view.scrollViewWith
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
import eu.kanade.tachiyomi.util.view.setStyle import eu.kanade.tachiyomi.util.view.setStyle
import eu.kanade.tachiyomi.util.view.snack import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.util.view.toolbarHeight
import eu.kanade.tachiyomi.util.view.updateLayoutParams import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.updatePaddingRelative import eu.kanade.tachiyomi.util.view.updatePaddingRelative
import eu.kanade.tachiyomi.util.view.withFadeTransaction import eu.kanade.tachiyomi.util.view.withFadeTransaction
@ -172,6 +177,10 @@ class MangaDetailsController :
var refreshTracker: Int? = null var refreshTracker: Int? = null
var chapterPopupMenu: Pair<Int, PopupMenu>? = null var chapterPopupMenu: Pair<Int, PopupMenu>? = null
// Tablet Layout
var isTablet = false
private var tabletAdapter: MangaDetailsAdapter? = null
private var query = "" private var query = ""
private var adapter: MangaDetailsAdapter? = null private var adapter: MangaDetailsAdapter? = null
@ -195,6 +204,7 @@ class MangaDetailsController :
coverColor = null coverColor = null
fullCoverActive = false fullCoverActive = false
setTabletMode(view)
setRecycler(view) setRecycler(view)
setPaletteColor() setPaletteColor()
adapter?.fastScroller = binding.fastScroller adapter?.fastScroller = binding.fastScroller
@ -208,6 +218,21 @@ class MangaDetailsController :
requestPermissionsSafe(arrayOf(WRITE_EXTERNAL_STORAGE), 301) requestPermissionsSafe(arrayOf(WRITE_EXTERNAL_STORAGE), 301)
} }
/** Check if device is tablet, and use a second recycler to hold the details header if so */
private fun setTabletMode(view: View) {
isTablet = view.context.isTablet() &&
view.context.resources.configuration?.orientation == Configuration.ORIENTATION_LANDSCAPE
binding.tabletOverlay.isVisible = isTablet
binding.tabletRecycler.isVisible = isTablet
binding.tabletDivider.isVisible = isTablet
if (isTablet) {
binding.recycler.updateLayoutParams<ViewGroup.LayoutParams> { width = 0 }
tabletAdapter = MangaDetailsAdapter(this)
binding.tabletRecycler.adapter = tabletAdapter
binding.tabletRecycler.layoutManager = LinearLayoutManager(view.context)
}
}
override fun onDestroyView(view: View) { override fun onDestroyView(view: View) {
snack?.dismiss() snack?.dismiss()
presenter.onDestroy() presenter.onDestroy()
@ -236,6 +261,14 @@ class MangaDetailsController :
binding.swipeRefresh.setDistanceToTriggerSync(70.dpToPx) binding.swipeRefresh.setDistanceToTriggerSync(70.dpToPx)
activityBinding!!.appBar.elevation = 0f activityBinding!!.appBar.elevation = 0f
if (isTablet) {
val tHeight = toolbarHeight.takeIf { it ?: 0 > 0 } ?: appbarHeight
headerHeight = tHeight + (activityBinding?.root?.rootWindowInsets?.systemWindowInsetTop ?: 0)
binding.recycler.updatePaddingRelative(top = headerHeight + 4.dpToPx)
binding.recycler.doOnApplyWindowInsets { _, insets, _ ->
setInsets(insets, appbarHeight, offset)
}
} else {
scrollViewWith( scrollViewWith(
binding.recycler, binding.recycler,
padBottom = true, padBottom = true,
@ -247,16 +280,19 @@ class MangaDetailsController :
colorToolbar(it) colorToolbar(it)
} }
) )
}
binding.recycler.addOnScrollListener( binding.recycler.addOnScrollListener(
object : RecyclerView.OnScrollListener() { object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy) super.onScrolled(recyclerView, dx, dy)
if (!isTablet) {
val atTop = !recyclerView.canScrollVertically(-1) val atTop = !recyclerView.canScrollVertically(-1)
val tY = getHeader()?.binding?.backdrop?.translationY ?: 0f val tY = getHeader()?.binding?.backdrop?.translationY ?: 0f
getHeader()?.binding?.backdrop?.translationY = max(0f, tY + dy * 0.25f) getHeader()?.binding?.backdrop?.translationY = max(0f, tY + dy * 0.25f)
if (atTop) getHeader()?.binding?.backdrop?.translationY = 0f if (atTop) getHeader()?.binding?.backdrop?.translationY = 0f
} }
}
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
val atTop = !recyclerView.canScrollVertically(-1) val atTop = !recyclerView.canScrollVertically(-1)
@ -268,9 +304,15 @@ class MangaDetailsController :
private fun setInsets(insets: WindowInsets, appbarHeight: Int, offset: Int) { private fun setInsets(insets: WindowInsets, appbarHeight: Int, offset: Int) {
binding.recycler.updatePaddingRelative(bottom = insets.systemWindowInsetBottom) binding.recycler.updatePaddingRelative(bottom = insets.systemWindowInsetBottom)
headerHeight = appbarHeight + insets.systemWindowInsetTop binding.tabletRecycler.updatePaddingRelative(bottom = insets.systemWindowInsetBottom)
val tHeight = toolbarHeight.takeIf { it ?: 0 > 0 } ?: appbarHeight
headerHeight = tHeight + insets.systemWindowInsetTop
binding.swipeRefresh.setProgressViewOffset(false, (-40).dpToPx, headerHeight + offset) binding.swipeRefresh.setProgressViewOffset(false, (-40).dpToPx, headerHeight + offset)
// 1dp extra to line up chapter header and manga header if (isTablet) {
binding.tabletOverlay.updateLayoutParams<ViewGroup.LayoutParams> { height = headerHeight }
// 4dp extra to line up chapter header and manga header
binding.recycler.updatePaddingRelative(top = headerHeight + 4.dpToPx)
}
getHeader()?.setTopHeight(headerHeight) getHeader()?.setTopHeight(headerHeight)
binding.fastScroller.updateLayoutParams<ViewGroup.MarginLayoutParams> { binding.fastScroller.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = headerHeight topMargin = headerHeight
@ -280,8 +322,8 @@ class MangaDetailsController :
} }
/** Set the toolbar to fully transparent or colored and translucent */ /** Set the toolbar to fully transparent or colored and translucent */
fun colorToolbar(isColor: Boolean, animate: Boolean = true) { private fun colorToolbar(isColor: Boolean, animate: Boolean = true) {
if (isColor == toolbarIsColored) return if (isColor == toolbarIsColored || (isTablet && isColor)) return
toolbarIsColored = isColor toolbarIsColored = isColor
val isCurrentController = val isCurrentController =
router?.backstack?.lastOrNull()?.controller == this@MangaDetailsController router?.backstack?.lastOrNull()?.controller == this@MangaDetailsController
@ -538,12 +580,14 @@ class MangaDetailsController :
} }
private fun getHeader(): MangaHeaderHolder? { private fun getHeader(): MangaHeaderHolder? {
return binding.recycler.findViewHolderForAdapterPosition(0) as? MangaHeaderHolder return if (isTablet) binding.tabletRecycler.findViewHolderForAdapterPosition(0) as? MangaHeaderHolder
else binding.recycler.findViewHolderForAdapterPosition(0) as? MangaHeaderHolder
} }
fun updateHeader() { fun updateHeader() {
binding.swipeRefresh.isRefreshing = presenter.isLoading binding.swipeRefresh.isRefreshing = presenter.isLoading
adapter?.setChapters(presenter.chapters) adapter?.setChapters(presenter.chapters)
tabletAdapter?.notifyDataSetChanged()
addMangaHeader() addMangaHeader()
activity?.invalidateOptionsMenu() activity?.invalidateOptionsMenu()
} }
@ -555,6 +599,7 @@ class MangaDetailsController :
launchUI { binding.swipeRefresh.isRefreshing = true } launchUI { binding.swipeRefresh.isRefreshing = true }
presenter.fetchChaptersFromSource() presenter.fetchChaptersFromSource()
} }
tabletAdapter?.notifyDataSetChanged()
adapter?.setChapters(chapters) adapter?.setChapters(chapters)
addMangaHeader() addMangaHeader()
colorToolbar(binding.recycler.canScrollVertically(-1)) colorToolbar(binding.recycler.canScrollVertically(-1))
@ -562,7 +607,12 @@ class MangaDetailsController :
} }
private fun addMangaHeader() { private fun addMangaHeader() {
if (adapter?.scrollableHeaders?.isEmpty() == true) { if (tabletAdapter?.scrollableHeaders?.isEmpty() == true) {
tabletAdapter?.removeAllScrollableHeaders()
tabletAdapter?.addScrollableHeader(presenter.headerItem)
adapter?.removeAllScrollableHeaders()
adapter?.addScrollableHeader(presenter.tabletChapterHeaderItem!!)
} else if (!isTablet && adapter?.scrollableHeaders?.isEmpty() == true) {
adapter?.removeAllScrollableHeaders() adapter?.removeAllScrollableHeaders()
adapter?.addScrollableHeader(presenter.headerItem) adapter?.addScrollableHeader(presenter.headerItem)
} }
@ -819,8 +869,10 @@ class MangaDetailsController :
setOnQueryTextChangeListener(searchView) { setOnQueryTextChangeListener(searchView) {
query = it ?: "" query = it ?: ""
if (!isTablet) {
if (query.isNotEmpty()) getHeader()?.collapse() if (query.isNotEmpty()) getHeader()?.collapse()
else getHeader()?.expand() else getHeader()?.expand()
}
adapter?.setFilter(query) adapter?.setFilter(query)
adapter?.performFilter() adapter?.performFilter()

View File

@ -46,6 +46,7 @@ import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.system.ImageUtil import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.manga.MangaShortcutManager import eu.kanade.tachiyomi.util.manga.MangaShortcutManager
import eu.kanade.tachiyomi.util.system.executeOnIO import eu.kanade.tachiyomi.util.system.executeOnIO
import eu.kanade.tachiyomi.util.system.isTablet
import eu.kanade.tachiyomi.util.system.launchIO import eu.kanade.tachiyomi.util.system.launchIO
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -97,8 +98,14 @@ class MangaDetailsPresenter(
private set private set
var headerItem = MangaHeaderItem(manga, controller.fromCatalogue) var headerItem = MangaHeaderItem(manga, controller.fromCatalogue)
var tabletChapterHeaderItem: MangaHeaderItem? = null
fun onCreate() { fun onCreate() {
headerItem.isTablet = controller.isTablet
if (controller.isTablet) {
tabletChapterHeaderItem = MangaHeaderItem(manga, false)
tabletChapterHeaderItem?.isChapterHeader = true
}
isLockedFromSearch = SecureActivityDelegate.shouldBeLocked() isLockedFromSearch = SecureActivityDelegate.shouldBeLocked()
headerItem.isLocked = isLockedFromSearch headerItem.isLocked = isLockedFromSearch
downloadManager.addListener(this) downloadManager.addListener(this)

View File

@ -15,6 +15,7 @@ import com.google.android.material.button.MaterialButton
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.image.coil.loadManga import eu.kanade.tachiyomi.data.image.coil.loadManga
import eu.kanade.tachiyomi.databinding.ChapterHeaderItemBinding
import eu.kanade.tachiyomi.databinding.MangaHeaderItemBinding import eu.kanade.tachiyomi.databinding.MangaHeaderItemBinding
import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
@ -28,24 +29,43 @@ import eu.kanade.tachiyomi.util.view.updateLayoutParams
class MangaHeaderHolder( class MangaHeaderHolder(
private val view: View, private val view: View,
private val adapter: MangaDetailsAdapter, private val adapter: MangaDetailsAdapter,
startExpanded: Boolean startExpanded: Boolean,
isTablet: Boolean = false
) : BaseFlexibleViewHolder(view, adapter) { ) : BaseFlexibleViewHolder(view, adapter) {
val binding = MangaHeaderItemBinding.bind(view) val binding: MangaHeaderItemBinding? = try {
MangaHeaderItemBinding.bind(view)
} catch (e: Exception) {
null
}
private val chapterBinding: ChapterHeaderItemBinding? = try {
ChapterHeaderItemBinding.bind(view)
} catch (e: Exception) {
null
}
private var showReadingButton = true private var showReadingButton = true
private var showMoreButton = true private var showMoreButton = true
var hadSelection = false var hadSelection = false
init { init {
binding.chapterLayout.setOnClickListener { adapter.delegate.showChapterFilter() }
binding.startReadingButton.setOnClickListener { adapter.delegate.readNextChapter() } if (binding == null) {
binding.topView.updateLayoutParams<ConstraintLayout.LayoutParams> { with(chapterBinding) {
this ?: return@with
chapterLayout.setOnClickListener { adapter.delegate.showChapterFilter() }
}
}
with(binding) {
this ?: return@with
chapterLayout.setOnClickListener { adapter.delegate.showChapterFilter() }
startReadingButton.setOnClickListener { adapter.delegate.readNextChapter() }
topView.updateLayoutParams<ConstraintLayout.LayoutParams> {
height = adapter.delegate.topCoverHeight() height = adapter.delegate.topCoverHeight()
} }
binding.moreButton.setOnClickListener { expandDesc() } moreButton.setOnClickListener { expandDesc() }
binding.mangaSummary.setOnClickListener { mangaSummary.setOnClickListener {
if (binding.moreButton.isVisible) { if (moreButton.isVisible) {
expandDesc() expandDesc()
} else if (!hadSelection) { } else if (!hadSelection) {
collapseDesc() collapseDesc()
@ -53,56 +73,66 @@ class MangaHeaderHolder(
hadSelection = false hadSelection = false
} }
} }
binding.mangaSummary.setOnLongClickListener { mangaSummary.setOnLongClickListener {
if (binding.mangaSummary.isTextSelectable && !adapter.recyclerView.canScrollVertically(-1)) { if (mangaSummary.isTextSelectable && !adapter.recyclerView.canScrollVertically(
(adapter.delegate as MangaDetailsController).binding.swipeRefresh.isEnabled = false -1
)
) {
(adapter.delegate as MangaDetailsController).binding.swipeRefresh.isEnabled =
false
} }
false false
} }
binding.mangaSummary.setOnTouchListener { _, event -> mangaSummary.setOnTouchListener { _, event ->
if (event.action == MotionEvent.ACTION_DOWN) { if (event.action == MotionEvent.ACTION_DOWN) {
view.requestFocus() view.requestFocus()
} }
if (event.actionMasked == MotionEvent.ACTION_UP) { if (event.actionMasked == MotionEvent.ACTION_UP) {
hadSelection = binding.mangaSummary.hasSelection() hadSelection = mangaSummary.hasSelection()
(adapter.delegate as MangaDetailsController).binding.swipeRefresh.isEnabled = (adapter.delegate as MangaDetailsController).binding.swipeRefresh.isEnabled =
true true
} }
false false
} }
if (!itemView.resources.isLTR) { if (!itemView.resources.isLTR) {
binding.moreBgGradient.rotation = 180f moreBgGradient.rotation = 180f
} }
binding.lessButton.setOnClickListener { collapseDesc() } lessButton.setOnClickListener { collapseDesc() }
binding.mangaGenresTags.setOnTagClickListener { mangaGenresTags.setOnTagClickListener {
adapter.delegate.tagClicked(it) adapter.delegate.tagClicked(it)
} }
binding.webviewButton.setOnClickListener { adapter.delegate.openInWebView() } webviewButton.setOnClickListener { adapter.delegate.openInWebView() }
binding.shareButton.setOnClickListener { adapter.delegate.prepareToShareManga() } shareButton.setOnClickListener { adapter.delegate.prepareToShareManga() }
binding.favoriteButton.setOnClickListener { favoriteButton.setOnClickListener {
adapter.delegate.favoriteManga(false) adapter.delegate.favoriteManga(false)
} }
binding.title.setOnClickListener { title.setOnClickListener {
binding.title.text?.let { adapter.delegate.globalSearch(it.toString()) } title.text?.let { adapter.delegate.globalSearch(it.toString()) }
} }
binding.title.setOnLongClickListener { title.setOnLongClickListener {
adapter.delegate.copyToClipboard(binding.title.text.toString(), R.string.title) adapter.delegate.copyToClipboard(title.text.toString(), R.string.title)
true true
} }
binding.mangaAuthor.setOnClickListener { mangaAuthor.setOnClickListener {
binding.mangaAuthor.text?.let { adapter.delegate.globalSearch(it.toString()) } mangaAuthor.text?.let { adapter.delegate.globalSearch(it.toString()) }
} }
binding.mangaAuthor.setOnLongClickListener { mangaAuthor.setOnLongClickListener {
adapter.delegate.copyToClipboard(binding.mangaAuthor.text.toString(), R.string.author) adapter.delegate.copyToClipboard(
mangaAuthor.text.toString(),
R.string.author
)
true true
} }
binding.mangaCover.setOnClickListener { adapter.delegate.zoomImageFromThumb(binding.coverCard) } mangaCover.setOnClickListener { adapter.delegate.zoomImageFromThumb(coverCard) }
binding.trackButton.setOnClickListener { adapter.delegate.showTrackingSheet() } trackButton.setOnClickListener { adapter.delegate.showTrackingSheet() }
if (startExpanded) expandDesc() if (startExpanded) expandDesc()
else collapseDesc() else collapseDesc()
if (isTablet) chapterLayout.isVisible = false
}
} }
private fun expandDesc() { private fun expandDesc() {
binding ?: return
if (binding.moreButton.visibility == View.VISIBLE) { if (binding.moreButton.visibility == View.VISIBLE) {
binding.mangaSummary.maxLines = Integer.MAX_VALUE binding.mangaSummary.maxLines = Integer.MAX_VALUE
binding.mangaSummary.setTextIsSelectable(true) binding.mangaSummary.setTextIsSelectable(true)
@ -110,10 +140,12 @@ class MangaHeaderHolder(
binding.lessButton.isVisible = true binding.lessButton.isVisible = true
binding.moreButtonGroup.isVisible = false binding.moreButtonGroup.isVisible = false
binding.title.maxLines = Integer.MAX_VALUE binding.title.maxLines = Integer.MAX_VALUE
binding.mangaSummary.requestFocus()
} }
} }
private fun collapseDesc() { private fun collapseDesc() {
binding ?: return
binding.mangaSummary.setTextIsSelectable(false) binding.mangaSummary.setTextIsSelectable(false)
binding.mangaSummary.isClickable = true binding.mangaSummary.isClickable = true
binding.mangaSummary.maxLines = 3 binding.mangaSummary.maxLines = 3
@ -129,13 +161,29 @@ class MangaHeaderHolder(
fun bindChapters() { fun bindChapters() {
val presenter = adapter.delegate.mangaPresenter() val presenter = adapter.delegate.mangaPresenter()
val count = presenter.chapters.size val count = presenter.chapters.size
binding.chaptersTitle.text = itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count) if (binding != null) {
binding.chaptersTitle.text =
itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count)
binding.filtersText.text = presenter.currentFilters() binding.filtersText.text = presenter.currentFilters()
} else if (chapterBinding != null) {
chapterBinding.chaptersTitle.text =
itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count)
chapterBinding.filtersText.text = presenter.currentFilters()
}
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
fun bind(item: MangaHeaderItem, manga: Manga) { fun bind(item: MangaHeaderItem, manga: Manga) {
val presenter = adapter.delegate.mangaPresenter() val presenter = adapter.delegate.mangaPresenter()
if (binding == null) {
if (chapterBinding != null) {
val count = presenter.chapters.size
chapterBinding.chaptersTitle.text =
itemView.resources.getQuantityString(R.plurals.chapters_plural, count, count)
chapterBinding.filtersText.text = presenter.currentFilters()
}
return
}
binding.title.text = manga.title binding.title.text = manga.title
if (manga.genre.isNullOrBlank().not()) binding.mangaGenresTags.setTags( if (manga.genre.isNullOrBlank().not()) binding.mangaGenresTags.setTags(
@ -281,16 +329,20 @@ class MangaHeaderHolder(
} }
fun setTopHeight(newHeight: Int) { fun setTopHeight(newHeight: Int) {
binding ?: return
if (newHeight == binding.topView.height) return
binding.topView.updateLayoutParams<ConstraintLayout.LayoutParams> { binding.topView.updateLayoutParams<ConstraintLayout.LayoutParams> {
height = newHeight height = newHeight
} }
} }
fun setBackDrop(color: Int) { fun setBackDrop(color: Int) {
binding ?: return
binding.trueBackdrop.setBackgroundColor(color) binding.trueBackdrop.setBackgroundColor(color)
} }
fun updateTracking() { fun updateTracking() {
binding ?: return
val presenter = adapter.delegate.mangaPresenter() val presenter = adapter.delegate.mangaPresenter()
val tracked = presenter.isTracked() val tracked = presenter.isTracked()
with(binding.trackButton) { with(binding.trackButton) {
@ -309,6 +361,7 @@ class MangaHeaderHolder(
} }
fun collapse() { fun collapse() {
binding ?: return
binding.subItemGroup.isVisible = false binding.subItemGroup.isVisible = false
binding.startReadingButton.isVisible = false binding.startReadingButton.isVisible = false
if (binding.moreButton.isVisible || binding.moreButton.isInvisible) { if (binding.moreButton.isVisible || binding.moreButton.isInvisible) {
@ -320,6 +373,7 @@ class MangaHeaderHolder(
} }
fun updateCover(manga: Manga) { fun updateCover(manga: Manga) {
binding ?: return
if (!manga.initialized) return if (!manga.initialized) return
val drawable = adapter.controller.binding.mangaCoverFull.drawable val drawable = adapter.controller.binding.mangaCoverFull.drawable
binding.mangaCover.loadManga( binding.mangaCover.loadManga(
@ -343,6 +397,7 @@ class MangaHeaderHolder(
} }
fun expand() { fun expand() {
binding ?: return
binding.subItemGroup.isVisible = true binding.subItemGroup.isVisible = true
if (!showMoreButton) binding.moreButtonGroup.isVisible = false if (!showMoreButton) binding.moreButtonGroup.isVisible = false
else { else {

View File

@ -13,6 +13,7 @@ class MangaHeaderItem(val manga: Manga, var startExpanded: Boolean) :
var isChapterHeader = false var isChapterHeader = false
var isLocked = false var isLocked = false
var isTablet = false
override fun getLayoutRes(): Int { override fun getLayoutRes(): Int {
return if (isChapterHeader) R.layout.chapter_header_item else R.layout.manga_header_item return if (isChapterHeader) R.layout.chapter_header_item else R.layout.manga_header_item
@ -27,7 +28,7 @@ class MangaHeaderItem(val manga: Manga, var startExpanded: Boolean) :
} }
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): MangaHeaderHolder { override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): MangaHeaderHolder {
return MangaHeaderHolder(view, adapter as MangaDetailsAdapter, startExpanded) return MangaHeaderHolder(view, adapter as MangaDetailsAdapter, startExpanded, isTablet)
} }
override fun bindViewHolder( override fun bindViewHolder(

View File

@ -31,11 +31,11 @@
android:id="@+id/webview_button" android:id="@+id/webview_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="20dp" android:layout_marginEnd="12dp"
android:background="@null" android:background="@null"
android:padding="5dp" android:padding="5dp"
android:src="@drawable/ic_filter_list_24dp" android:src="@drawable/ic_filter_list_24dp"
android:tint="?colorAccent" app:tint="?colorAccent"
app:layout_constraintBottom_toBottomOf="@id/chapters_title" app:layout_constraintBottom_toBottomOf="@id/chapters_title"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/chapters_title" /> app:layout_constraintTop_toTopOf="@id/chapters_title" />

View File

@ -13,19 +13,58 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?android:colorBackground"> android:background="?android:colorBackground">
<androidx.constraintlayout.widget.ConstraintLayout
<FrameLayout
android:id="@+id/linear_recycler_layout" android:id="@+id/linear_recycler_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/tablet_recycler"
android:layout_width="0dp"
android:layout_height="match_parent"
android:clipToPadding="false"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/recycler"
app:layout_constraintWidth_percent="0.4"
tools:itemCount="1"
tools:listitem="@layout/manga_header_item" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler" android:id="@+id/recycler"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:clipToPadding="false" android:clipToPadding="false"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tablet_recycler"
tools:listitem="@layout/chapters_item" /> tools:listitem="@layout/chapters_item" />
</FrameLayout>
<View
android:id="@+id/tablet_overlay"
android:visibility="gone"
android:background="?android:attr/colorBackground"
android:alpha=".80"
android:layout_width="0dp"
android:layout_height="20dp"
app:layout_constraintWidth_percent=".6"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<View
android:id="@+id/tablet_divider"
android:visibility="gone"
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="@color/divider"
app:layout_constraintEnd_toStartOf="@id/tablet_overlay"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<eu.kanade.tachiyomi.ui.base.MaterialFastScroll <eu.kanade.tachiyomi.ui.base.MaterialFastScroll
@ -45,7 +84,6 @@
android:visibility="invisible" android:visibility="invisible"
tools:background="@color/md_black_1000" /> tools:background="@color/md_black_1000" />
<ImageView <ImageView
android:id="@+id/manga_cover_full" android:id="@+id/manga_cover_full"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -356,6 +356,7 @@
android:tooltipText="@string/sort_and_filter" android:tooltipText="@string/sort_and_filter"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/start_reading_button"> app:layout_constraintTop_toBottomOf="@id/start_reading_button">
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView