Unify list spacing approach
parent
61a7f1c830
commit
2342594885
@ -1,106 +0,0 @@
|
||||
package org.koitharu.kotatsu.core.ui
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.LayoutParams
|
||||
import androidx.activity.OnBackPressedDispatcher
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.ui.dialog.AppBottomSheetDialog
|
||||
import org.koitharu.kotatsu.core.util.ext.findActivity
|
||||
import org.koitharu.kotatsu.core.util.ext.getDisplaySize
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
@Deprecated(
|
||||
"Use BaseAdaptiveSheet",
|
||||
replaceWith = ReplaceWith("BaseAdaptiveSheet<B>", "org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet"),
|
||||
)
|
||||
abstract class BaseBottomSheet<B : ViewBinding> : BottomSheetDialogFragment() {
|
||||
|
||||
var viewBinding: B? = null
|
||||
private set
|
||||
|
||||
@Deprecated("", ReplaceWith("requireViewBinding()"))
|
||||
protected val binding: B
|
||||
get() = requireViewBinding()
|
||||
|
||||
protected val behavior: BottomSheetBehavior<*>?
|
||||
get() = (dialog as? BottomSheetDialog)?.behavior
|
||||
|
||||
val isExpanded: Boolean
|
||||
get() = behavior?.state == BottomSheetBehavior.STATE_EXPANDED
|
||||
|
||||
val onBackPressedDispatcher: OnBackPressedDispatcher
|
||||
get() = (requireDialog() as AppBottomSheetDialog).onBackPressedDispatcher
|
||||
|
||||
final override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?,
|
||||
): View {
|
||||
val binding = onCreateViewBinding(inflater, container)
|
||||
viewBinding = binding
|
||||
return binding.root
|
||||
}
|
||||
|
||||
final override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val binding = requireViewBinding()
|
||||
// Enforce max width for tablets
|
||||
val width = resources.getDimensionPixelSize(R.dimen.bottom_sheet_width)
|
||||
if (width > 0) {
|
||||
behavior?.maxWidth = width
|
||||
}
|
||||
// Set peek height to 40% display height
|
||||
binding.root.context.findActivity()?.getDisplaySize()?.let {
|
||||
behavior?.peekHeight = (it.height() * 0.4).toInt()
|
||||
}
|
||||
onViewBindingCreated(binding, savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
viewBinding = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
return AppBottomSheetDialog(requireContext(), theme)
|
||||
}
|
||||
|
||||
fun addBottomSheetCallback(callback: BottomSheetBehavior.BottomSheetCallback) {
|
||||
val b = behavior ?: return
|
||||
b.addBottomSheetCallback(callback)
|
||||
val rootView = dialog?.findViewById<View>(materialR.id.design_bottom_sheet)
|
||||
if (rootView != null) {
|
||||
callback.onStateChanged(rootView, b.state)
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): B
|
||||
|
||||
protected open fun onViewBindingCreated(binding: B, savedInstanceState: Bundle?) = Unit
|
||||
|
||||
protected fun setExpanded(isExpanded: Boolean, isLocked: Boolean) {
|
||||
val b = behavior ?: return
|
||||
if (isExpanded) {
|
||||
b.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
}
|
||||
b.isFitToContents = !isExpanded
|
||||
val rootView = dialog?.findViewById<View>(materialR.id.design_bottom_sheet)
|
||||
rootView?.updateLayoutParams {
|
||||
height = if (isExpanded) LayoutParams.MATCH_PARENT else LayoutParams.WRAP_CONTENT
|
||||
}
|
||||
b.isDraggable = !isLocked
|
||||
}
|
||||
|
||||
fun requireViewBinding(): B = checkNotNull(viewBinding) {
|
||||
"Fragment $this did not return a ViewBinding from onCreateView() or this was called before onCreateView()."
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
package org.koitharu.kotatsu.core.ui.list.decor
|
||||
|
||||
import android.graphics.Rect
|
||||
import android.util.SparseIntArray
|
||||
import android.view.View
|
||||
import androidx.core.util.getOrDefault
|
||||
import androidx.core.util.set
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
class TypedSpacingItemDecoration(
|
||||
vararg spacingMapping: Pair<Int, Int>,
|
||||
private val fallbackSpacing: Int = 0,
|
||||
) : RecyclerView.ItemDecoration() {
|
||||
|
||||
private val mapping = SparseIntArray(spacingMapping.size)
|
||||
|
||||
init {
|
||||
spacingMapping.forEach { (k, v) -> mapping[k] = v }
|
||||
}
|
||||
|
||||
override fun getItemOffsets(
|
||||
outRect: Rect,
|
||||
view: View,
|
||||
parent: RecyclerView,
|
||||
state: RecyclerView.State
|
||||
) {
|
||||
val itemType = parent.getChildViewHolder(view)?.itemViewType
|
||||
val spacing = if (itemType == null) {
|
||||
fallbackSpacing
|
||||
} else {
|
||||
mapping.getOrDefault(itemType, fallbackSpacing)
|
||||
}
|
||||
outRect.set(spacing, spacing, spacing, spacing)
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package org.koitharu.kotatsu.filter.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.koitharu.kotatsu.R
|
||||
|
||||
class FilterItemDecoration(
|
||||
context: Context,
|
||||
) : RecyclerView.ItemDecoration() {
|
||||
|
||||
private val spacing = context.resources.getDimensionPixelOffset(R.dimen.list_spacing)
|
||||
|
||||
override fun getItemOffsets(
|
||||
outRect: Rect,
|
||||
view: View,
|
||||
parent: RecyclerView,
|
||||
state: RecyclerView.State
|
||||
) {
|
||||
val itemType = parent.getChildViewHolder(view)?.itemViewType ?: -1
|
||||
if (itemType == FilterAdapter.ITEM_TYPE_HEADER) {
|
||||
outRect.set(spacing, 0, spacing, 0)
|
||||
} else {
|
||||
outRect.set(0, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package org.koitharu.kotatsu.list.ui.adapter
|
||||
|
||||
enum class ListItemType {
|
||||
|
||||
FILTER_SORT,
|
||||
FILTER_TAG,
|
||||
HEADER,
|
||||
MANGA_LIST,
|
||||
MANGA_LIST_DETAILED,
|
||||
MANGA_GRID,
|
||||
FOOTER_LOADING,
|
||||
FOOTER_ERROR,
|
||||
STATE_LOADING,
|
||||
STATE_ERROR,
|
||||
STATE_EMPTY,
|
||||
EXPLORE_BUTTONS,
|
||||
EXPLORE_SOURCE_GRID,
|
||||
EXPLORE_SOURCE_LIST,
|
||||
EXPLORE_SUGGESTION,
|
||||
TIP,
|
||||
HINT_EMPTY,
|
||||
PAGE_THUMB,
|
||||
FEED,
|
||||
DOWNLOAD,
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package org.koitharu.kotatsu.list.ui.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.ItemDecoration
|
||||
import org.koitharu.kotatsu.R
|
||||
|
||||
class TypedListSpacingDecoration(
|
||||
context: Context,
|
||||
) : ItemDecoration() {
|
||||
|
||||
private val spacingList = context.resources.getDimensionPixelOffset(R.dimen.list_spacing)
|
||||
private val spacingGrid = context.resources.getDimensionPixelOffset(R.dimen.grid_spacing)
|
||||
|
||||
override fun getItemOffsets(
|
||||
outRect: Rect,
|
||||
view: View,
|
||||
parent: RecyclerView,
|
||||
state: RecyclerView.State
|
||||
) {
|
||||
val itemType = parent.getChildViewHolder(view)?.itemViewType?.let {
|
||||
ListItemType.values().getOrNull(it)
|
||||
}
|
||||
when (itemType) {
|
||||
ListItemType.FILTER_SORT,
|
||||
ListItemType.FILTER_TAG -> outRect.set(0)
|
||||
|
||||
ListItemType.HEADER -> outRect.set(spacingList, 0, spacingList, 0)
|
||||
ListItemType.MANGA_LIST -> outRect.set(0)
|
||||
ListItemType.DOWNLOAD,
|
||||
ListItemType.MANGA_LIST_DETAILED -> outRect.set(spacingList)
|
||||
|
||||
ListItemType.PAGE_THUMB,
|
||||
ListItemType.MANGA_GRID -> outRect.set(spacingGrid)
|
||||
|
||||
ListItemType.FOOTER_LOADING,
|
||||
ListItemType.FOOTER_ERROR,
|
||||
ListItemType.STATE_LOADING,
|
||||
ListItemType.STATE_ERROR,
|
||||
ListItemType.STATE_EMPTY,
|
||||
ListItemType.EXPLORE_BUTTONS,
|
||||
ListItemType.EXPLORE_SOURCE_GRID,
|
||||
ListItemType.EXPLORE_SOURCE_LIST,
|
||||
ListItemType.EXPLORE_SUGGESTION,
|
||||
null -> outRect.set(0)
|
||||
|
||||
ListItemType.TIP -> outRect.set(0) // TODO
|
||||
ListItemType.HINT_EMPTY -> outRect.set(0) // TODO
|
||||
ListItemType.FEED -> outRect.set(0) // TODO
|
||||
}
|
||||
}
|
||||
|
||||
private fun Rect.set(spacing: Int) = set(spacing, spacing, spacing, spacing)
|
||||
}
|
||||
Loading…
Reference in New Issue