I've recently been running into varied issues using a RecyclerView and PagedListAdapter with multiple view types. The reason for different view types was essentially to add section headers. Switching to using ItemDecoration seemed much more stable and a better pattern.
So I thought I'd do the same thing with another RecyclerView, trying to eliminate multiple view types so each row in the RecyclerView corresponded to an item in the underlying PagedList. The problem is, this time it isn't a simple section header TextView. It's a CardView.
I had a bit of trouble getting the width right (this CardView is meant to be MATCH_PARENT). I think I figured that out, but I have another problem. The CardView is drawing, but without the background shadow. I see from StackOverflow questions like Why is my cardview not being drawn onto canvas? that other people have the same problem. It seems elevation shadows are not drawn with regular layout/measure/draw functionality.
How can I get my CardView shadow in the ItemDecoration? Is there a way?
This is what I have currently:
class CardItemDecoration(val adapter: ReservationAdapter) : RecyclerView.ItemDecoration() {
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
super.getItemOffsets(outRect, view, parent, state)
val position = parent.getChildAdapterPosition(view)
if (adapter.hasCard && position == 0) {
outRect.top = getcardView(parent.context, parent).measuredHeight
}
}
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
super.onDraw(c, parent, state)
val left = parent.paddingLeft
val right = parent.width - parent.paddingRight
if (adapter.hascard && parent.childCount > 0) {
val child = parent.getChildAt(0)
val layout = getCardView(parent.context, parent)
// Draw in the space made by getItemOffsets()
layout.layout(left, 0, right, layout.measuredHeight)
c.save()
// Adjust Y coordinates, as they'll be different for each row
val top = child.top - layout.measuredHeight
c.translate(0f, top.toFloat())
layout.draw(c)
c.restore()
}
}
private lateinit var cardView: ViewGroup
private fun getCardView(context: Context, parent: RecyclerView): View {
if (!::cardView.isInitialized) {
cardView = LinearLayout(context)
LayoutInflater.from(context).inflate(R.layout.call_out_bis_profile, cardView, true)
cardView.apply {
findViewById<TextView>(R.id.infoTextView).text = context.getString(R.string.card_description)
}
val width = parent.width - parent.paddingLeft - parent.paddingRight
cardView.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED))
}
return cardView
}
}