Last active
July 3, 2019 04:52
-
-
Save IhwanID/6b3ae512f07216e198f0dc70ebc63823 to your computer and use it in GitHub Desktop.
costum itemdecoration
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
| import android.content.res.Resources | |
| import android.graphics.Rect | |
| import android.view.View | |
| import androidx.recyclerview.widget.RecyclerView | |
| class CardStackSpacingItemDecoration : RecyclerView.ItemDecoration() { | |
| private val dp = Resources.getSystem().displayMetrics.density | |
| override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { | |
| val position = parent.getChildAdapterPosition(view) | |
| if (position != 0) | |
| outRect.top = (-24 * dp).toInt() | |
| } | |
| } |
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
| import android.content.res.Resources | |
| import android.graphics.Rect | |
| import android.view.View | |
| import androidx.recyclerview.widget.RecyclerView | |
| import com.thoughtbot.expandablerecyclerview.models.ExpandableListPosition | |
| class GridSpacingItemDecoration( | |
| private val spanCount: Int, private val spacing: Int | |
| ) : RecyclerView.ItemDecoration() { | |
| private val dp = Resources.getSystem().displayMetrics.density | |
| override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { | |
| val position = parent.getChildAdapterPosition(view) // item position | |
| if(parent.adapter?.getItemViewType(position) == ExpandableListPosition.CHILD){ | |
| val paddingHorizontal = (8 * dp).toInt() | |
| val paddingBottom = (16 * dp).toInt() | |
| outRect.left = paddingHorizontal | |
| outRect.right = paddingHorizontal | |
| outRect.bottom = paddingBottom | |
| }else{ | |
| val paddingHorizontal = (8 * dp).toInt() | |
| outRect.right = paddingHorizontal | |
| } | |
| } | |
| } |
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
| import android.content.res.Resources | |
| import android.graphics.Canvas | |
| import android.graphics.Color | |
| import android.graphics.Paint | |
| import android.graphics.Rect | |
| import android.view.View | |
| import android.view.animation.AccelerateDecelerateInterpolator | |
| import androidx.recyclerview.widget.LinearLayoutManager | |
| import androidx.recyclerview.widget.RecyclerView | |
| class HorizontalSpacingItemDecoration : RecyclerView.ItemDecoration() { | |
| private val colorActive = Color.parseColor("#f6932c") | |
| private val colorInactive = Color.parseColor("#e7e7eb") | |
| private val dp = Resources.getSystem().displayMetrics.density | |
| /** | |
| * Height of the space the indicator takes up at the bottom of the view. | |
| */ | |
| private val mIndicatorHeight = dp * 8 | |
| /** | |
| * Indicator stroke width. | |
| */ | |
| private val mIndicatorStrokeWidth = dp * 4 | |
| /** | |
| * Indicator width. | |
| */ | |
| private val mIndicatorItemLength = dp * 4 | |
| /** | |
| * Padding between indicators. | |
| */ | |
| private val mIndicatorItemPadding = dp * 8 | |
| /** | |
| * Some more natural animation interpolation | |
| */ | |
| private val mInterpolator = AccelerateDecelerateInterpolator() | |
| private val mPaint = Paint() | |
| init { | |
| mPaint.strokeWidth = mIndicatorStrokeWidth | |
| mPaint.style = Paint.Style.STROKE | |
| mPaint.isAntiAlias = true | |
| } | |
| override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { | |
| super.onDraw(c, parent, state) | |
| val itemCount = parent.adapter?.itemCount ?:0 | |
| // center horizontally, calculate width and subtract half from center | |
| val totalLength = mIndicatorItemLength * itemCount | |
| val paddingBetweenItems = Math.max(0, itemCount - 1) * mIndicatorItemPadding | |
| val indicatorTotalWidth = totalLength + paddingBetweenItems | |
| val indicatorStartX = (parent.width - indicatorTotalWidth) / 2f | |
| // center vertically in the allotted space | |
| val indicatorPosY = parent.height - mIndicatorHeight / 2f | |
| drawInactiveIndicators(c, indicatorStartX, indicatorPosY, itemCount) | |
| // find active page (which should be highlighted) | |
| val layoutManager = parent.layoutManager as LinearLayoutManager | |
| val activePosition = layoutManager.findFirstVisibleItemPosition() | |
| if (activePosition == RecyclerView.NO_POSITION) { | |
| return | |
| } | |
| // find offset of active page (if the user is scrolling) | |
| val activeChild = layoutManager.findViewByPosition(activePosition) | |
| val left = activeChild?.left ?:0 | |
| val width = activeChild?.width ?:0 | |
| // on swipe the active item will be positioned from [-width, 0] | |
| // interpolate offset for smooth animation | |
| val progress = mInterpolator.getInterpolation(left * -1 / width.toFloat()) | |
| drawHighlights(c, indicatorStartX, indicatorPosY, activePosition, progress) | |
| } | |
| private fun drawInactiveIndicators(c: Canvas, indicatorStartX: Float, indicatorPosY: Float, itemCount: Int) { | |
| mPaint.color = colorInactive | |
| // width of item indicator including padding | |
| val itemWidth = mIndicatorItemLength + mIndicatorItemPadding | |
| var start = indicatorStartX | |
| for (i in 0 until itemCount) { | |
| c.drawCircle(start, indicatorPosY, mIndicatorItemLength / 2f, mPaint) | |
| start += itemWidth | |
| } | |
| } | |
| private fun drawHighlights(c: Canvas, indicatorStartX: Float, indicatorPosY: Float, | |
| highlightPosition: Int, progress: Float) { | |
| mPaint.color = colorActive | |
| // width of item indicator including padding | |
| val itemWidth = mIndicatorItemLength + mIndicatorItemPadding | |
| if (progress == 0f) { | |
| // no swipe, draw a normal indicator | |
| val highlightStart = indicatorStartX + itemWidth * highlightPosition | |
| c.drawCircle(highlightStart, indicatorPosY, mIndicatorItemLength / 2f, mPaint) | |
| } else { | |
| val highlightStart = indicatorStartX + itemWidth * highlightPosition | |
| // calculate partial highlight | |
| val partialLength = mIndicatorItemLength * progress + mIndicatorItemPadding * progress | |
| c.drawCircle(highlightStart + partialLength, indicatorPosY, mIndicatorItemLength / 2f, mPaint) | |
| } | |
| } | |
| override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { | |
| val leftPadding = (24 * dp).toInt() | |
| val rightPadding = (16 * dp).toInt() | |
| parent.clipToPadding = false | |
| parent.setPadding(leftPadding, 0, rightPadding, 0) | |
| outRect.right = (8 * dp).toInt() | |
| outRect.bottom = (16 * dp).toInt() | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment