Improve thumbnails bs
This commit is contained in:
@@ -25,6 +25,7 @@ import org.koitharu.kotatsu.details.ui.model.ChapterListItem
|
|||||||
import org.koitharu.kotatsu.download.ui.service.DownloadService
|
import org.koitharu.kotatsu.download.ui.service.DownloadService
|
||||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity
|
import org.koitharu.kotatsu.reader.ui.ReaderActivity
|
||||||
import org.koitharu.kotatsu.reader.ui.ReaderState
|
import org.koitharu.kotatsu.reader.ui.ReaderState
|
||||||
|
import org.koitharu.kotatsu.utils.RecyclerViewScrollCallback
|
||||||
|
|
||||||
class ChaptersFragment : BaseFragment<FragmentChaptersBinding>(),
|
class ChaptersFragment : BaseFragment<FragmentChaptersBinding>(),
|
||||||
OnListItemClickListener<ChapterListItem>,
|
OnListItemClickListener<ChapterListItem>,
|
||||||
@@ -211,7 +212,17 @@ class ChaptersFragment : BaseFragment<FragmentChaptersBinding>(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun onChaptersChanged(list: List<ChapterListItem>) {
|
private fun onChaptersChanged(list: List<ChapterListItem>) {
|
||||||
chaptersAdapter?.items = list
|
val adapter = chaptersAdapter ?: return
|
||||||
|
if (adapter.itemCount == 0) {
|
||||||
|
val position = list.indexOfFirst { it.hasFlag(ChapterListItem.FLAG_CURRENT) } - 1
|
||||||
|
if (position > 0) {
|
||||||
|
adapter.setItems(list, RecyclerViewScrollCallback(binding.recyclerViewChapters, position))
|
||||||
|
} else {
|
||||||
|
adapter.items = list
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
adapter.items = list
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onLoadingStateChanged(isLoading: Boolean) {
|
private fun onLoadingStateChanged(isLoading: Boolean) {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.divider.MaterialDividerItemDecoration
|
import com.google.android.material.divider.MaterialDividerItemDecoration
|
||||||
import org.koin.android.ext.android.get
|
import org.koin.android.ext.android.get
|
||||||
@@ -19,6 +18,7 @@ import org.koitharu.kotatsu.details.ui.adapter.ChaptersAdapter
|
|||||||
import org.koitharu.kotatsu.details.ui.model.ChapterListItem
|
import org.koitharu.kotatsu.details.ui.model.ChapterListItem
|
||||||
import org.koitharu.kotatsu.details.ui.model.toListItem
|
import org.koitharu.kotatsu.details.ui.model.toListItem
|
||||||
import org.koitharu.kotatsu.utils.BottomSheetToolbarController
|
import org.koitharu.kotatsu.utils.BottomSheetToolbarController
|
||||||
|
import org.koitharu.kotatsu.utils.RecyclerViewScrollCallback
|
||||||
import org.koitharu.kotatsu.utils.ext.withArgs
|
import org.koitharu.kotatsu.utils.ext.withArgs
|
||||||
|
|
||||||
class ChaptersBottomSheet : BaseBottomSheet<SheetChaptersBinding>(), OnListItemClickListener<ChapterListItem> {
|
class ChaptersBottomSheet : BaseBottomSheet<SheetChaptersBinding>(), OnListItemClickListener<ChapterListItem> {
|
||||||
@@ -58,7 +58,7 @@ class ChaptersBottomSheet : BaseBottomSheet<SheetChaptersBinding>(), OnListItemC
|
|||||||
binding.recyclerView.adapter = ChaptersAdapter(this).also { adapter ->
|
binding.recyclerView.adapter = ChaptersAdapter(this).also { adapter ->
|
||||||
if (currentPosition >= 0) {
|
if (currentPosition >= 0) {
|
||||||
val targetPosition = (currentPosition - 1).coerceAtLeast(0)
|
val targetPosition = (currentPosition - 1).coerceAtLeast(0)
|
||||||
adapter.setItems(items, Scroller(binding.recyclerView, targetPosition))
|
adapter.setItems(items, RecyclerViewScrollCallback(binding.recyclerView, targetPosition))
|
||||||
} else {
|
} else {
|
||||||
adapter.items = items
|
adapter.items = items
|
||||||
}
|
}
|
||||||
@@ -77,13 +77,6 @@ class ChaptersBottomSheet : BaseBottomSheet<SheetChaptersBinding>(), OnListItemC
|
|||||||
fun onChapterChanged(chapter: MangaChapter)
|
fun onChapterChanged(chapter: MangaChapter)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Scroller(private val recyclerView: RecyclerView, private val position: Int) : Runnable {
|
|
||||||
override fun run() {
|
|
||||||
val offset = recyclerView.resources.getDimensionPixelSize(R.dimen.chapter_list_item_height) / 2
|
|
||||||
(recyclerView.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(position, offset)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private const val ARG_CHAPTERS = "chapters"
|
private const val ARG_CHAPTERS = "chapters"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import org.koin.android.ext.android.get
|
import org.koin.android.ext.android.get
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
@@ -28,6 +28,7 @@ class PagesThumbnailsSheet : BaseBottomSheet<SheetPagesBinding>(),
|
|||||||
|
|
||||||
private lateinit var thumbnails: List<PageThumbnail>
|
private lateinit var thumbnails: List<PageThumbnail>
|
||||||
private val spanResolver = MangaListSpanResolver()
|
private val spanResolver = MangaListSpanResolver()
|
||||||
|
private var currentPageIndex = -1
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -36,12 +37,12 @@ class PagesThumbnailsSheet : BaseBottomSheet<SheetPagesBinding>(),
|
|||||||
dismissAllowingStateLoss()
|
dismissAllowingStateLoss()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val current = arguments?.getInt(ARG_CURRENT, -1) ?: -1
|
currentPageIndex = requireArguments().getInt(ARG_CURRENT, currentPageIndex)
|
||||||
val repository = mangaRepositoryOf(pages.first().source)
|
val repository = mangaRepositoryOf(pages.first().source)
|
||||||
thumbnails = pages.mapIndexed { i, x ->
|
thumbnails = pages.mapIndexed { i, x ->
|
||||||
PageThumbnail(
|
PageThumbnail(
|
||||||
number = i + 1,
|
number = i + 1,
|
||||||
isCurrent = i == current,
|
isCurrent = i == currentPageIndex,
|
||||||
repository = repository,
|
repository = repository,
|
||||||
page = x
|
page = x
|
||||||
)
|
)
|
||||||
@@ -68,11 +69,9 @@ class PagesThumbnailsSheet : BaseBottomSheet<SheetPagesBinding>(),
|
|||||||
resources.getQuantityString(R.plurals.pages, thumbnails.size, thumbnails.size)
|
resources.getQuantityString(R.plurals.pages, thumbnails.size, thumbnails.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
val initialTopPosition = binding.recyclerView.top
|
|
||||||
|
|
||||||
with(binding.recyclerView) {
|
with(binding.recyclerView) {
|
||||||
addItemDecoration(
|
addItemDecoration(
|
||||||
SpacingItemDecoration(view.resources.getDimensionPixelOffset(R.dimen.grid_spacing))
|
SpacingItemDecoration(resources.getDimensionPixelOffset(R.dimen.grid_spacing))
|
||||||
)
|
)
|
||||||
adapter = PageThumbnailAdapter(
|
adapter = PageThumbnailAdapter(
|
||||||
thumbnails,
|
thumbnails,
|
||||||
@@ -81,16 +80,12 @@ class PagesThumbnailsSheet : BaseBottomSheet<SheetPagesBinding>(),
|
|||||||
get(),
|
get(),
|
||||||
this@PagesThumbnailsSheet
|
this@PagesThumbnailsSheet
|
||||||
)
|
)
|
||||||
addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
|
||||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) = Unit
|
|
||||||
|
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
|
||||||
super.onScrolled(recyclerView, dx, dy)
|
|
||||||
binding.appbar.isLifted = getChildAt(0).top < initialTopPosition
|
|
||||||
}
|
|
||||||
})
|
|
||||||
addOnLayoutChangeListener(spanResolver)
|
addOnLayoutChangeListener(spanResolver)
|
||||||
spanResolver.setGridSize(get<AppSettings>().gridSize / 100f, this)
|
spanResolver.setGridSize(get<AppSettings>().gridSize / 100f, this)
|
||||||
|
if (currentPageIndex > 0) {
|
||||||
|
val offset = resources.getDimensionPixelOffset(R.dimen.preferred_grid_width)
|
||||||
|
(layoutManager as GridLayoutManager).scrollToPositionWithOffset(currentPageIndex, offset)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import org.koitharu.kotatsu.local.data.PagesCache
|
|||||||
import org.koitharu.kotatsu.reader.ui.thumbnails.PageThumbnail
|
import org.koitharu.kotatsu.reader.ui.thumbnails.PageThumbnail
|
||||||
import org.koitharu.kotatsu.utils.ext.IgnoreErrors
|
import org.koitharu.kotatsu.utils.ext.IgnoreErrors
|
||||||
import org.koitharu.kotatsu.utils.ext.referer
|
import org.koitharu.kotatsu.utils.ext.referer
|
||||||
|
import org.koitharu.kotatsu.utils.ext.setTextColorAttr
|
||||||
|
import com.google.android.material.R as materialR
|
||||||
|
|
||||||
fun pageThumbnailAD(
|
fun pageThumbnailAD(
|
||||||
coil: ImageLoader,
|
coil: ImageLoader,
|
||||||
@@ -31,7 +33,7 @@ fun pageThumbnailAD(
|
|||||||
height = (gridWidth * 13f / 18f).toInt()
|
height = (gridWidth * 13f / 18f).toInt()
|
||||||
)
|
)
|
||||||
|
|
||||||
binding.handle.setOnClickListener {
|
binding.root.setOnClickListener {
|
||||||
clickListener.onItemClick(item.page, itemView)
|
clickListener.onItemClick(item.page, itemView)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +41,8 @@ fun pageThumbnailAD(
|
|||||||
job?.cancel()
|
job?.cancel()
|
||||||
binding.imageViewThumb.setImageDrawable(null)
|
binding.imageViewThumb.setImageDrawable(null)
|
||||||
with(binding.textViewNumber) {
|
with(binding.textViewNumber) {
|
||||||
setBackgroundResource(if (item.isCurrent) R.drawable.bg_badge_accent else R.drawable.bg_badge_default)
|
setBackgroundResource(if (item.isCurrent) R.drawable.bg_badge_accent else R.drawable.bg_badge_empty)
|
||||||
|
setTextColorAttr(if (item.isCurrent) materialR.attr.colorOnTertiary else android.R.attr.textColorPrimary)
|
||||||
text = (item.number).toString()
|
text = (item.number).toString()
|
||||||
}
|
}
|
||||||
job = scope.launch(Dispatchers.Default + IgnoreErrors) {
|
job = scope.launch(Dispatchers.Default + IgnoreErrors) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import org.koitharu.kotatsu.core.model.Manga
|
|||||||
import org.koitharu.kotatsu.databinding.ItemSearchSuggestionMangaGridBinding
|
import org.koitharu.kotatsu.databinding.ItemSearchSuggestionMangaGridBinding
|
||||||
import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener
|
import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener
|
||||||
import org.koitharu.kotatsu.search.ui.suggestion.model.SearchSuggestionItem
|
import org.koitharu.kotatsu.search.ui.suggestion.model.SearchSuggestionItem
|
||||||
import org.koitharu.kotatsu.utils.ScrollResetCallback
|
import org.koitharu.kotatsu.utils.RecyclerViewScrollCallback
|
||||||
import org.koitharu.kotatsu.utils.ext.enqueueWith
|
import org.koitharu.kotatsu.utils.ext.enqueueWith
|
||||||
import org.koitharu.kotatsu.utils.ext.newImageRequest
|
import org.koitharu.kotatsu.utils.ext.newImageRequest
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ fun searchSuggestionMangaListAD(
|
|||||||
right = recyclerView.paddingRight - spacing,
|
right = recyclerView.paddingRight - spacing,
|
||||||
)
|
)
|
||||||
recyclerView.addItemDecoration(SpacingItemDecoration(spacing))
|
recyclerView.addItemDecoration(SpacingItemDecoration(spacing))
|
||||||
val scrollResetCallback = ScrollResetCallback(recyclerView)
|
val scrollResetCallback = RecyclerViewScrollCallback(recyclerView, 0)
|
||||||
|
|
||||||
bind {
|
bind {
|
||||||
adapter.setItems(item.items, scrollResetCallback)
|
adapter.setItems(item.items, scrollResetCallback)
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package org.koitharu.kotatsu.utils
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import java.lang.ref.WeakReference
|
||||||
|
|
||||||
|
class RecyclerViewScrollCallback(recyclerView: RecyclerView, private val position: Int) : Runnable {
|
||||||
|
|
||||||
|
private val recyclerViewRef = WeakReference(recyclerView)
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
val rv = recyclerViewRef.get() ?: return
|
||||||
|
val lm = rv.layoutManager ?: return
|
||||||
|
rv.stopScroll()
|
||||||
|
if (lm is LinearLayoutManager) {
|
||||||
|
lm.scrollToPositionWithOffset(position, 0)
|
||||||
|
} else {
|
||||||
|
lm.scrollToPosition(position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package org.koitharu.kotatsu.utils
|
|
||||||
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import java.lang.ref.WeakReference
|
|
||||||
|
|
||||||
class ScrollResetCallback(recyclerView: RecyclerView) : Runnable {
|
|
||||||
|
|
||||||
private val recyclerViewRef = WeakReference(recyclerView)
|
|
||||||
|
|
||||||
override fun run() {
|
|
||||||
recyclerViewRef.get()?.scrollToPosition(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,9 @@ package org.koitharu.kotatsu.utils.ext
|
|||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.annotation.AttrRes
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.core.content.res.use
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
|
|
||||||
var TextView.textAndVisible: CharSequence?
|
var TextView.textAndVisible: CharSequence?
|
||||||
@@ -35,4 +37,11 @@ fun TextView.setTextAndVisible(@StringRes textResId: Int) {
|
|||||||
setText(textResId)
|
setText(textResId)
|
||||||
isGone = text.isNullOrEmpty()
|
isGone = text.isNullOrEmpty()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun TextView.setTextColorAttr(@AttrRes attrResId: Int) {
|
||||||
|
val colors = context.obtainStyledAttributes(intArrayOf(attrResId)).use {
|
||||||
|
it.getColorStateList(0)
|
||||||
|
}
|
||||||
|
setTextColor(colors)
|
||||||
}
|
}
|
||||||
15
app/src/main/res/drawable/bg_badge_empty.xml
Normal file
15
app/src/main/res/drawable/bg_badge_empty.xml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<corners android:radius="5dp" />
|
||||||
|
<solid android:color="?colorBackgroundFloating" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="?colorOutline" />
|
||||||
|
<padding
|
||||||
|
android:bottom="2dp"
|
||||||
|
android:left="2dp"
|
||||||
|
android:right="2dp"
|
||||||
|
android:top="2dp" />
|
||||||
|
</shape>
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout
|
<com.google.android.material.card.MaterialCardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/scrimBackground">
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
style="@style/Widget.Material3.CardView.Outlined"
|
||||||
|
app:cardBackgroundColor="?scrimBackground">
|
||||||
|
|
||||||
<org.koitharu.kotatsu.base.ui.widgets.CoverImageView
|
<org.koitharu.kotatsu.base.ui.widgets.CoverImageView
|
||||||
android:id="@+id/imageView_thumb"
|
android:id="@+id/imageView_thumb"
|
||||||
@@ -13,18 +15,12 @@
|
|||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
tools:src="@drawable/ic_placeholder" />
|
tools:src="@drawable/ic_placeholder" />
|
||||||
|
|
||||||
<View
|
|
||||||
android:id="@+id/handle"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="?selectableItemBackground" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textView_number"
|
android:id="@+id/textView_number"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom|end"
|
android:layout_gravity="bottom|end"
|
||||||
android:layout_margin="8dp"
|
android:layout_margin="4dp"
|
||||||
android:ellipsize="none"
|
android:ellipsize="none"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:minWidth="26dp"
|
android:minWidth="26dp"
|
||||||
@@ -34,4 +30,4 @@
|
|||||||
tools:background="@drawable/bg_badge_default"
|
tools:background="@drawable/bg_badge_default"
|
||||||
tools:text="2" />
|
tools:text="2" />
|
||||||
|
|
||||||
</FrameLayout>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
Reference in New Issue
Block a user