Created
March 7, 2021 15:35
-
-
Save OmarKRostom/24bd66a43032199ca3e97e00656b4c58 to your computer and use it in GitHub Desktop.
Final version of the ArcLayoutManager
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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
