Я создал нижний колонтитул в RecyclerView, переопределив RecyclerView.ItemDecoration (). Он содержит кнопку изображения со стрелкой, направленной вверх, и нарисован на холсте.
Я хочу добиться эффекта ряби при нажатии кнопки изображения.
![Footer](https://i.stack.imgur.com/fLFiI.png)
Я хотел бы воспользоваться советами о том, как было бы намного проще просто добавить элемент другого типа в список. Я не могу использовать этот способ, так как он сталкивается с другими частями кода. Поэтому я должен придерживаться этого решения.
FooterItemDecorator
private const val SCROLL_TO_TOP_ICON_SIZE_IN_DP = 52
class FooterItemDecorator(
context: Context,
parent: RecyclerView,
val onFooterClicked: () -> Unit
) : RecyclerView.ItemDecoration() {
private val footerView = LayoutInflater.from(context).inflate(R.layout.item_scroll_to_top, parent, false)
private var iconBounds: IconBounds? = null
private val onFooterTouchListener = object: RecyclerView.OnItemTouchListener {
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
if (e.action == MotionEvent.ACTION_UP && iconBounds?.iconClicked(e.x, e.y) == true) {
onFooterClicked()
}
return false
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
}
init {
footerView.measure(makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
makeMeasureSpec(0, MeasureSpec.UNSPECIFIED))
parent.addOnItemTouchListener(onFooterTouchListener)
}
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
super.onDraw(c, parent, state)
footerView.layout(parent.left, 0, parent.right, footerView.measuredHeight)
val adapterItemsCount = parent.adapter?.itemCount ?: -1
if (adapterItemsCount > 1) {
for (i in 0 until parent.childCount) {
val view = parent.getChildAt(i)
if (parent.getChildAdapterPosition(view) == adapterItemsCount - 1) {
c.save()
c.translate(0F, view.bottom.toFloat())
footerView.draw(c)
if (iconBounds == null) {
iconBounds = getIconBounds(parent.bottom, footerView.measuredHeight, parent.right)
}
c.restore()
break
}
}
}
}
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
val itemsCount = parent.adapter?.itemCount ?: -1
if (itemsCount > 1 && parent.getChildAdapterPosition(view) == itemsCount - 1) {
outRect.set(0, 0, 0, footerView.measuredHeight)
} else {
outRect.setEmpty()
}
}
}
private data class IconBounds(
val left: Int,
val top: Int,
val right: Int,
val bottom: Int
)
private fun IconBounds.iconClicked(touchX: Float, touchY: Float)
= touchX.toInt() in left..right && touchY.toInt() in top..bottom
private fun getIconBounds(parentBottom: Int, footerHeight: Int, recyclerWidth: Int): IconBounds {
val footerTop = parentBottom - footerHeight
val iconHorizontalCenter = recyclerWidth / 2
val iconVerticalCenter = footerTop + (footerHeight / 2)
val iconRadius = (SCROLL_TO_TOP_ICON_SIZE_IN_DP / 2).dpToPx()
return IconBounds(
left = iconHorizontalCenter - iconRadius,
top = iconVerticalCenter - iconRadius,
right = iconHorizontalCenter + iconRadius,
bottom = iconVerticalCenter + iconRadius
)
}