I have a strange problem on Android API 28 with the ItemTouchHelper
where it doesn't draw one of the icons on swiping. Did they change something in the new version that I'm not aware of?
Edit icon is shown in API 27 but not on API 28.
Delete icon is shown on both API versions.
The calculated position of the icons is the same on both versions.
Log for delete icon
API 27: D/Position: Left: 938 Top: 100 Right: 1001 Bottom: 163
API 28: D/Position: Left: 938 Top: 100 Right: 1001 Bottom: 163
Log for edit icon
API 27: D/Position: Left: 142 Top: 100 Right: 79 Bottom: 163
API 28: D/Position: Left: 142 Top: 100 Right: 79 Bottom: 163
ItemTouchHelper
abstract class ImageGroupTouchCallback(context: Context) : ItemTouchHelper.Callback() {
[...] -> unimportant code removed
override fun onChildDraw(c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder,
dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) {
[...] -> unimportant stuff
// Calculate position of the icon
val iconMargin = (itemHeight - intrinsicHeight) / 2
val iconTop = itemView.top + (itemHeight - intrinsicHeight) / 2
val iconBottom = iconTop + intrinsicHeight
val (iconLeft, iconRight) = getIconPositionHorizontal(itemView, iconMargin, dX)
Log.d("Position", "Left: $iconLeft Top: $iconTop Right: $iconRight Bottom: $iconBottom")
// swiping from left to right
if (dX > 0) {
background.setBounds(itemView.left, itemView.top, itemView.left + dX.toInt(), itemView.bottom)
background.color = Color.parseColor("#3cca59")
background.draw(c)
// Draw the delete icon
editIcon!!.setBounds(iconLeft, iconTop, iconRight, iconBottom)
editIcon.draw(c)
}
// swiping from right to left
else if (dX < 0) {
background.setBounds(itemView.right + dX.toInt(), itemView.top, itemView.right, itemView.bottom)
background.color = Color.parseColor("#f44336")
background.draw(c)
// Draw the delete icon
deleteIcon!!.setBounds(iconLeft, iconTop, iconRight, iconBottom)
deleteIcon.draw(c)
}
}
private fun getIconPositionHorizontal(itemView: View, iconMargin: Int, dX: Float): Pair<Int, Int> {
val iconLeft: Int
val iconRight: Int
// swiping from left to right
if (dX > 0) {
iconLeft = itemView.left + iconMargin + intrinsicWidth
iconRight = itemView.left + iconMargin
} else {
iconLeft = itemView.right - iconMargin - intrinsicWidth
iconRight = itemView.right - iconMargin
}
return Pair(iconLeft, iconRight)
}
}
The left and right bounds on your edit icon are reversed.
// swiping from left to right if (dX > 0) { iconLeft = itemView.left + iconMargin + intrinsicWidth iconRight = itemView.left + iconMargin }
This will return a pair of coordinates where the value for the icon's left side is greater than the value for its right side. Your delete icon, on the other hand, has its coordinates set correctly.
Replace the above code with this:
// swiping from left to right
if (dX > 0) {
iconLeft = itemView.left + iconMargin
iconRight = itemView.left + iconMargin + intrinsicWidth
}
To reproduce this problem I created an incredibly simple view class:
public class MyView extends View {
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Drawable icon = ContextCompat.getDrawable(getContext(), R.drawable.ic_bookmark_black_24dp);
icon.setBounds(getRight(), getTop(), getLeft(), getBottom());
icon.draw(canvas);
}
}
And then I just stuck one of these into a layout as the only view in my activity:
<?xml version="1.0" encoding="utf-8"?>
<com.example.stackoverflow.MyView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
When I run the app, I don't see anything.
If I switch this line:
icon.setBounds(getRight(), getTop(), getLeft(), getBottom());
to be this instead:
icon.setBounds(getLeft(), getTop(), getRight(), getBottom());
then everything works as expected, and I see my icon filling the screen.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With