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
/** | |
* Called when fab is clicked to open filter sheet (open = true) | |
* or called when closeIcon is clicked to close the filter sheet (open = false) | |
* | |
* It's a 3 step animation played in sequence. Read the comments to know more. | |
*/ | |
private fun openFilterSheet(open: Boolean) { | |
// 1) Fab Arc Path Animator | |
// Animates path of the fab from starting position to centre of screen |
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
class NoScrollRecyclerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) | |
: RecyclerView(context, attrs, defStyleAttr) { | |
override fun scrollBy(x: Int, y: Int) { | |
val lm = layoutManager as? NoScrollHorizontalLayoutManager | |
lm?.canScrollHorizontally = true | |
super.scrollBy(x, y) | |
lm?.canScrollHorizontally = false | |
} | |
} |
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
tabsRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { | |
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { | |
totalTabsScroll += dx | |
} | |
}) | |
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { | |
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { | |
// Scroll tabs as viewpager is scrolled | |
val dx = (position + positionOffset) * tabItemWidth - totalTabsScroll |
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
private fun expandItem(holder: ListViewHolder, expand: Boolean, animate: Boolean) { | |
if (animate) { | |
val animator = getValueAnimator( | |
expand, listItemExpandDuration, AccelerateDecelerateInterpolator() | |
) { progress -> | |
holder.cardContainer.layoutParams.height = | |
(originalHeight + (expandedHeight - originalHeight) * progress).toInt() | |
holder.cardContainer.layoutParams.width = | |
(originalWidth + (expandedWidth - originalWidth) * progress).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
cardContainer.doOnLayout { view -> | |
originalHeight = view.height | |
// show expandView and record expandedHeight in next | |
// layout pass (doOnNextLayout) and hide it immediately | |
expandView.isVisible = true | |
cardContainer.doOnNextLayout { view -> | |
expandedHeight = view.height | |
// We use post{} to hide the view. Otherwise the parent will not |
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
inline fun <T : View> T.doOnGlobalLayout(crossinline action: () -> Unit) { | |
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { | |
override fun onGlobalLayout() { | |
viewTreeObserver.removeOnGlobalLayoutListener(this) | |
action() | |
} | |
}) | |
} |
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
inline fun getValueAnimator(forward: Boolean = true, duration: Long, interpolator: TimeInterpolator, | |
crossinline updateListener: (progress: Float) -> Unit | |
): ValueAnimator { | |
val a = | |
if (forward) ValueAnimator.ofFloat(0f, 1f) | |
else ValueAnimator.ofFloat(1f, 0f) | |
a.addUpdateListener { updateListener(it.animatedValue as Float) } | |
a.duration = duration | |
a.interpolator = interpolator | |
return a |
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
override fun onBindViewHolder(holder: ListViewHolder, position: Int) { | |
val model = adapterList[position] | |
// set expand state on binded items because views are recycler | |
expandItem(holder, model == expandedModel, animate = false) | |
holder.cardContainer.setOnClickListener { | |
if (expandedModel == null) { | |
// expand clicked view | |
expandItem(holder, expand = true, animate = true) |
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
class ToolbarBehavior : CoordinatorLayout.Behavior<AppBarLayout>() { | |
/** Consume if vertical scroll because we don't care about other scrolls */ | |
override fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout, child: AppBarLayout, | |
directTargetChild: View, target: View, axes: Int, type: Int): Boolean { | |
getViews(child) | |
return axes == ViewCompat.SCROLL_AXIS_VERTICAL || | |
super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, axes, type) | |
} |