android - 绘制透明区域未使用拖动监听器更新

标签 android drag-and-drop android-canvas paint porter-duff

我从 SO 上的自定义 ViewGroup 看到很多关于子 Views 上的 transparent 背景的问题,但是似乎没有人有这个问题。

背景:
我创建了一个自定义的 FrameLayout;这个容器有动态添加的 View 。它的 child 应该有一个透明的背景,但容器的另一个表面必须有一个背景颜色。 subview 可以拖放到这个容器的任何地方。

我的工作:
我重写了 dispatchDraw(),创建了一个 Bitmap 和一个新的 Canvas,然后用白色背景填充了新的 Canvas。
我在 subview 上循环,创建一个新的 Paint,一个来自子维度的 Rect 并使用 PorterDuff.Mode.DST_OUT 清除子维度区域。对于每个 child ,我将 Paint 和 Rect 添加到新的 Canvas 中。
最后,我通过传递创建的位图在 dispatchDraw() 给出的主 Canvas 上使用 drawBitmap

问题:
这很有效: children 有一个透明的背景,其余的都是白色背景。但是,当我向 child 添加 DragListener 时,“剪切”区域不会更新(而 dispatchDraw 被正确调用):换句话说,当我拖动 subview ,它很好地下降了,但透明区域仍然在同一个地方。

代码:
自定义 FrameLayout:

@Override
public void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(canvas);
    drawCanvas(canvas);
}

private void drawCanvas(Canvas canvas) {
    // Create an off-screen bitmap and its canvas
    Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
    Canvas auxCanvas = new Canvas(bitmap);

    // Fill the canvas with the desired outside color
    auxCanvas.drawColor(Color.WHITE);

    // Create a paint for each child into parent
    for (int i = 0; i < getChildCount(); ++i) {
        // Create a transparent area for the Rect child
        View child = this.getChildAt(i);
        Paint childPaint = new Paint();
        childPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
        Rect childRect = new Rect(child.getLeft(), child.getTop(), child.getRight(), child.getBottom());
        auxCanvas.drawRect(childRect, childPaint);
    }

    // Draw the bitmap into the original canvas
    canvas.drawBitmap(bitmap, 0, 0, null);
}

带有ACTION_DROP事件的DragListener:

case DragEvent.ACTION_DROP:
    x = event.getX();
    y = event.getY();

    FrameLayout frame = (FrameLayout) v;
    View view = (View) event.getLocalState();
    view.setX(x - (view.getWidth()/2));
    view.setY(y - (view.getHeight()/2));
    frame.invalidate();
    break;

截图:

关于我发现的所有问答,我尝试了很多方法,但似乎没有任何效果。
任何帮助将不胜感激。

最佳答案

最后,我找到了线索:透明 Paint 在更新后没有获得正确的 x 和 y 轴值。

我猜 getLeft()getTop()getRight()getBottom() 不'发生下降时改变。奇怪的是,在我的日志中,这些值似乎已更新。因此,我尝试使用 getX()getY()DragEvent.ACTION_DROP 中更新值,它正确地更改了坐标的透明区域。

循环中 child 的解决方法:

Paint childPaint = new Paint();
childPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
// Use the x and y axis (plus the width and height)
Rect childRect = new Rect(
    (int) child.getX(),
    (int) child.getY(),
    (int) child.getX() + child.getWidth(),
    (int) child.getY() + child.getHeight()
);
auxCanvas.drawRect(childRect, childPaint);

关于android - 绘制透明区域未使用拖动监听器更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36731276/

相关文章:

android - 在 ListView 中拖放

android - 如何将项目从一个 gridview 拖放到同一布局中的另一个 gridview?

android:合并文本和图像时更改了文本大小

android - 如何在我的 MapActivity 中添加上千个 GeoPoints

android - smoothScrollToPosition() 仅在 Android ICS 中滚动到一半?

javascript - 从网格拖放到树上,无需添加树节点

java - 在距离 10 的圆内画一个圆

android - 填充完整的 Canvas ,但保留边界填充区域,因为它像圆形、矩形

java - 通知 RecyclerView 中 Firestore 数据的更改

java - KeyStore 未返回正确的 key