【问题标题】:ItemTouchHelper onChildDraw() in API 28API 28 中的 ItemTouchHelper onChildDraw()
【发布时间】:2018-10-07 01:07:55
【问题描述】:

我在使用 ItemTouchHelper 的 Android API 28 上遇到了一个奇怪的问题,它不会在滑动时绘制其中一个图标。他们是否在新版本中更改了一些我不知道的内容?

编辑图标在 API 27 中显示,但在 API 28 中不显示。

删除图标显示在两个 API 版本上。

两个版本的图标计算位置相同。

删除图标的日志

API 27: D/Position: Left: 938 Top: 100 Right: 1001 Bottom: 163
API 28: D/Position: Left: 938 Top: 100 Right: 1001 Bottom: 163

日志编辑图标

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)
    }
}

【问题讨论】:

  • 编辑图标不存在还是被隐藏了?检查布局检查器以验证这一点。如果有,请检查海拔高度。
  • 图标和颜色绘制在画布上,因此布局检查器中没有视图元素。因此海拔不应该是问题。
  • “计算图标的位置和其他不重要的东西”的省略代码是否有错误?有趣的是,setBounds() 调用这两个图标使用了完全相同的一组参数......也许铅笔正在绘制在视图的右侧?我不知道为什么这在 API 27 和 28 之间会有所不同,但是嘿。
  • @BenP。我添加了省略的代码。我有一个函数getIconPositionHorizontal(),它考虑了滑动方向。正如您在日志中看到的那样,位置是相同的,不应绘制在右侧。那是我不明白的。我开始认为这是 Android 方面的错误。
  • 对于编辑图标,left 位置大于right 位置。我可以看到这反转了图标的水平方向,但我也可以看到 Android 认为这是非法的并且根本不绘制图标。这绝对是一种可能会在 api 版本之间发生变化的事情。

标签: android


【解决方案1】:

编辑图标的左右边界是相反的。

// swiping from left to right
if (dX > 0) {
    iconLeft = itemView.left + iconMargin + intrinsicWidth
    iconRight = itemView.left + iconMargin
}

这将返回一对坐标,其中图标左侧的值大于其右侧的值。另一方面,您的删除图标的坐标设置正确。

将上面的代码替换为:

// swiping from left to right
if (dX > 0) {
    iconLeft = itemView.left + iconMargin
    iconRight = itemView.left + iconMargin + intrinsicWidth
}

为了重现这个问题,我创建了一个非常简单的视图类:

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);
    }
}

然后我只是将其中一个粘贴到布局中,作为我活动中的唯一视图:

<?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"/>

当我运行应用程序时,我什么也看不到。

如果我切换这一行:

icon.setBounds(getRight(), getTop(), getLeft(), getBottom());

改为:

icon.setBounds(getLeft(), getTop(), getRight(), getBottom());

然后一切正常,我看到我的图标填满了屏幕。

【讨论】:

  • 我明白了,它现在可以工作了!太感谢了。如果没有你的帮助,我不会发现 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-22
  • 2019-03-09
  • 2019-02-02
  • 2020-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多