Skip to content

Instantly share code, notes, and snippets.

@zakrodionov
Created July 19, 2019 08:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zakrodionov/6c6ddb62d9c4bc18d1a69f2d3cfe4146 to your computer and use it in GitHub Desktop.
Save zakrodionov/6c6ddb62d9c4bc18d1a69f2d3cfe4146 to your computer and use it in GitHub Desktop.
expand delegate, item in recyclerview #view
// Example
fun expandAdapterDelegate() = adapterDelegateLayoutContainer<ExpandedItem, DisplayableItem>(R.layout.item_expanded) {
llArrowContainer.setOnClickListener {
val isExpand = !item.isExpanded
item.isExpanded = isExpand
expandText(isExpand, ivArrow, llTextContainer)
}
bind {
tvNumber.text = item.number.toString()
expandText(item.isExpanded, ivArrow, llTextContainer, 0L)
}
}
fun expandText(isExpanded: Boolean, ivArrow: ImageView, llContainer: LinearLayout, duration: Long = 300L){
if (!isExpanded) {
if (ivArrow.rotation != 360f) {
ivArrow.rotate(duration, 180f, 360f)
}
collapse(llContainer, duration)
} else {
if (ivArrow.rotation != 180f) {
ivArrow.rotate(duration, 360f, 180f)
}
expand(llContainer, duration)
}
}
data class ExpandedItem(var isExpanded: Boolean = false, val number: Int): DisplayableItem
object Extension {
fun View.rotate(duration: Long, from: Float, to: Float) {
val rotation = ObjectAnimator.ofFloat(this, "rotation", from, to)
rotation.duration = duration
rotation.start()
}
fun View.animateAlpha(visibility: Int, duration: Long) {
setVisibility(visibility)
val startValue: Float
val endValue: Float
when (visibility){
View.GONE, View.INVISIBLE -> { startValue = 1f; endValue = 0f }
View.VISIBLE -> { startValue = 0f; endValue = 1f }
else -> { startValue = 0f; endValue = 1f}
}
val anim = ObjectAnimator.ofFloat(this, "alpha", startValue, endValue)
anim.duration = duration
anim.start()
}
fun View.slideToBottom(duration: Long) {
val animate = TranslateAnimation(0f, 0f, 0f, this.height.toFloat())
animate.duration = duration
animate.fillAfter = true
this.startAnimation(animate)
this.visibility = View.GONE
}
fun View.slideToTop(duration: Long) {
val animate = TranslateAnimation(0f, 0f, this.height.toFloat(), 0f)
animate.duration = duration
animate.fillAfter = true
this.startAnimation(animate)
this.visibility = View.VISIBLE
}
fun expand(v: View, duration: Long) {
val matchParentMeasureSpec = View.MeasureSpec.makeMeasureSpec((v.parent as View).width, View.MeasureSpec.EXACTLY)
val wrapContentMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
v.measure(matchParentMeasureSpec, wrapContentMeasureSpec)
val targetHeight = v.measuredHeight
// Older versions of android (pre API 21) cancel animations for views with a height of 0.
v.layoutParams.height = 1
v.visibility = View.VISIBLE
val a = object : Animation() {
override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
v.layoutParams.height = if (interpolatedTime == 1f)
ViewGroup.LayoutParams.WRAP_CONTENT
else
(targetHeight * interpolatedTime).toInt()
v.requestLayout()
}
override fun willChangeBounds(): Boolean {
return true
}
}
// Expansion speed of 1dp/ms
a.duration = duration
v.startAnimation(a)
}
fun collapse(v: View, duration: Long) {
val initialHeight = v.measuredHeight
val a = object : Animation() {
override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
if (interpolatedTime == 1f) {
v.visibility = View.GONE
} else {
v.layoutParams.height = initialHeight - (initialHeight * interpolatedTime).toInt()
v.requestLayout()
}
}
override fun willChangeBounds(): Boolean {
return true
}
}
// Collapse speed of 1dp/ms
a.duration = duration
v.startAnimation(a)
}
}
class MainListAdapter(activity: Activity) : ListDelegationAdapter<List<DisplayableItem>>(
AdvertisementAdapterDelegate(activity),
catAdapterDelegate(),
DogAdapterDelegate(activity),
GeckoAdapterDelegate(activity),
SnakeListItemAdapterDelegate(activity),
expandedAdapterDelegate()
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment