cloudstream/app/src/main/java/com/lagradost/cloudstream3/ui/CustomRecyclerViews.kt

193 lines
5.8 KiB
Kotlin
Raw Normal View History

2021-05-12 21:51:02 +00:00
package com.lagradost.cloudstream3.ui
import android.content.Context
import android.util.AttributeSet
import android.view.View
import androidx.core.view.children
2021-05-12 21:51:02 +00:00
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlin.math.abs
2023-01-28 22:38:02 +00:00
class GrdLayoutManager(val context: Context, _spanCount: Int) :
GridLayoutManager(context, _spanCount) {
2021-05-12 21:51:02 +00:00
override fun onFocusSearchFailed(
focused: View,
focusDirection: Int,
recycler: RecyclerView.Recycler,
state: RecyclerView.State
): View? {
return try {
val fromPos = getPosition(focused)
val nextPos = getNextViewPos(fromPos, focusDirection)
findViewByPosition(nextPos)
} catch (e: Exception) {
null
}
}
2023-07-28 02:18:28 +00:00
/*override fun onRequestChildFocus(
2021-05-12 21:51:02 +00:00
parent: RecyclerView,
state: RecyclerView.State,
child: View,
focused: View?
): Boolean {
// android.widget.FrameLayout$LayoutParams cannot be cast to androidx.recyclerview.widget.RecyclerView$LayoutParams
return try {
2023-07-28 02:18:28 +00:00
if(focused != null) {
// val pos = maxOf(0, getPosition(focused) - 2) // IDK WHY
val pos = getPosition(focused)
if(pos >= 0) parent.scrollToPosition(pos)
}
2021-05-12 21:51:02 +00:00
super.onRequestChildFocus(parent, state, child, focused)
2023-01-28 22:38:02 +00:00
} catch (e: Exception) {
2021-05-12 21:51:02 +00:00
false
}
2023-07-28 02:18:28 +00:00
}*/
2021-05-12 21:51:02 +00:00
// Allows moving right and left with focus https://gist.github.com/vganin/8930b41f55820ec49e4d
override fun onInterceptFocusSearch(focused: View, direction: Int): View? {
return try {
val fromPos = getPosition(focused)
val nextPos = getNextViewPos(fromPos, direction)
findViewByPosition(nextPos)
} catch (e: Exception) {
null
}
}
private fun getNextViewPos(fromPos: Int, direction: Int): Int {
val offset = calcOffsetToNextView(direction)
if (hitBorder(fromPos, offset)) {
return fromPos
}
return fromPos + offset
}
private fun calcOffsetToNextView(direction: Int): Int {
2022-03-20 22:31:56 +00:00
val spanCount = this.spanCount
2021-05-12 21:51:02 +00:00
val orientation = this.orientation
2023-07-28 02:18:28 +00:00
// fixes arabic by inverting left and right layout focus
val correctDirection = if (this.isLayoutRTL) {
when (direction) {
2023-07-28 02:18:28 +00:00
View.FOCUS_RIGHT -> View.FOCUS_LEFT
View.FOCUS_LEFT -> View.FOCUS_RIGHT
else -> direction
}
} else direction
2021-05-12 21:51:02 +00:00
if (orientation == VERTICAL) {
2023-07-28 02:18:28 +00:00
when (correctDirection) {
2021-05-12 21:51:02 +00:00
View.FOCUS_DOWN -> {
return spanCount
}
2021-05-12 21:51:02 +00:00
View.FOCUS_UP -> {
return -spanCount
}
2021-05-12 21:51:02 +00:00
View.FOCUS_RIGHT -> {
return 1
}
2021-05-12 21:51:02 +00:00
View.FOCUS_LEFT -> {
return -1
}
}
} else if (orientation == HORIZONTAL) {
2023-07-28 02:18:28 +00:00
when (correctDirection) {
2021-05-12 21:51:02 +00:00
View.FOCUS_DOWN -> {
return 1
}
2021-05-12 21:51:02 +00:00
View.FOCUS_UP -> {
return -1
}
2021-05-12 21:51:02 +00:00
View.FOCUS_RIGHT -> {
return spanCount
}
2021-05-12 21:51:02 +00:00
View.FOCUS_LEFT -> {
return -spanCount
}
}
}
return 0
}
private fun hitBorder(from: Int, offset: Int): Boolean {
val spanCount = spanCount
return if (abs(offset) == 1) {
val spanIndex = from % spanCount
val newSpanIndex = spanIndex + offset
newSpanIndex < 0 || newSpanIndex >= spanCount
} else {
val newPos = from + offset
newPos in spanCount..-1
}
}
}
2021-10-09 21:59:37 +00:00
// https://riptutorial.com/android/example/4810/gridlayoutmanager-with-dynamic-span-count
2021-05-12 21:51:02 +00:00
class AutofitRecyclerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
RecyclerView(context, attrs) {
private val manager = GrdLayoutManager(context, 2) // THIS CONTROLS SPANS
private var columnWidth = -1
var spanCount = 0
set(value) {
field = value
if (value > 0) {
manager.spanCount = value
}
}
val itemWidth: Int
get() = measuredWidth / manager.spanCount
init {
if (attrs != null) {
val attrsArray = intArrayOf(android.R.attr.columnWidth)
val array = context.obtainStyledAttributes(attrs, attrsArray)
columnWidth = array.getDimensionPixelSize(0, -1)
array.recycle()
}
layoutManager = manager
}
}
/**
* Recyclerview wherein the max item width or height is set by the biggest view to prevent inconsistent view sizes.
*/
class MaxRecyclerView(ctx: Context, attrs: AttributeSet) : RecyclerView(ctx, attrs) {
private var biggestObserved: Int = 0
private val orientation = LayoutManager.getProperties(context, attrs, 0, 0).orientation
private val isHorizontal = orientation == HORIZONTAL
private fun View.updateMaxSize() {
if (isHorizontal) {
this.minimumHeight = biggestObserved
} else {
this.minimumWidth = biggestObserved
}
}
override fun onChildAttachedToWindow(child: View) {
child.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED)
val observed = if (isHorizontal) child.measuredHeight else child.measuredWidth
if (observed > biggestObserved) {
biggestObserved = observed
children.forEach { it.updateMaxSize() }
} else {
child.updateMaxSize()
}
super.onChildAttachedToWindow(child)
}
2021-05-12 21:51:02 +00:00
}