Skip to content

Instantly share code, notes, and snippets.

@OmarKRostom
Created March 7, 2021 15:35
Show Gist options
  • Save OmarKRostom/24bd66a43032199ca3e97e00656b4c58 to your computer and use it in GitHub Desktop.
Save OmarKRostom/24bd66a43032199ca3e97e00656b4c58 to your computer and use it in GitHub Desktop.
Final version of the ArcLayoutManager
package com.omarkrostom.arclayoutmanager
import android.content.Context
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import androidx.recyclerview.widget.RecyclerView
import kotlin.math.*
class ArcLayoutManager(
private val context: Context,
private var horizontalOffset: Int = 0
) : RecyclerView.LayoutManager() {
override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams =
RecyclerView.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
override fun canScrollHorizontally(): Boolean = true
override fun scrollHorizontallyBy(
dx: Int,
recycler: RecyclerView.Recycler?,
state: RecyclerView.State?
): Int {
horizontalOffset += dx
fill(recycler, state)
return dx
}
override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State?) {
super.onLayoutChildren(recycler, state)
fill(recycler, state)
}
private fun fill(recycler: RecyclerView.Recycler?, state: RecyclerView.State?) {
detachAndScrapAttachedViews(recycler ?: return)
for (itemIndex in 0 until itemCount) {
val view = recycler.getViewForPosition(itemIndex)
addView(view)
val viewWidth = pxFromDp(context, 90f)
val viewHeight = pxFromDp(context, 90f)
val left = (itemIndex * viewWidth) - horizontalOffset
val right = left + viewWidth
val top = computeYComponent((left + right) / 2, viewHeight)
val bottom = top.first + viewHeight
val alpha = top.second
view.rotation = (alpha * (180 / PI)).toFloat() - 90f
measureChildWithMargins(view ?: return, viewWidth.toInt(), viewHeight.toInt())
layoutDecoratedWithMargins(
view,
left.toInt(),
top.first.toInt(),
right.toInt(),
bottom.toInt()
)
}
recycler.scrapList.toList().forEach {
recycler.recycleView(it.itemView)
}
}
private fun computeYComponent(viewCenterX: Float,
h: Float): Pair<Int, Double> {
val screenWidth = context.resources.displayMetrics.widthPixels
val s = screenWidth.toDouble() / 2
val radius = (h * h + s * s) / (h * 2)
val xScreenFraction = viewCenterX.toDouble() / screenWidth.toDouble()
val beta = acos(s / radius)
val alpha = beta + (xScreenFraction * (Math.PI - (2 * beta)))
val yComponent = radius - (radius * sin(alpha))
return Pair(yComponent.toInt(), alpha)
}
private fun pxFromDp(context: Context, dp: Float): Float {
return dp * context.resources.displayMetrics.density
}
}
@tppandey
Copy link

hi i tried the above layout manager, its not showing any things, its displaying as empty screen , will u please help me out on this
Screenshot from 2021-12-14 10-42-35

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment