绘制透明区域未使用拖动侦听器更新
Drawing transparent area not updating with drag listener
我在 child Views
上从 SO 上的自定义 ViewGroup
看到了很多关于 transparent
背景的问题,但是似乎没有人遇到这个问题。
背景:
我创建了一个自定义 FrameLayout
;这个容器有动态添加的视图。它的 children 应该有透明背景,但容器的另一个表面必须有背景颜色。 children 视图可以 drag'n'dropped
此容器中的任何位置。
我是做什么的:
我重写 dispatchDraw()
,创建一个 Bitmap
和一个新的 Canvas
,然后用白色背景填充新的 Canvas。
我在 children Views 上循环,从 child 的维度创建一个新的 Paint
,一个 Rect
并使用 PorterDuff.Mode.DST_OUT
清除 child的区域。对于每个 child,我将 Paint 和 Rect 添加到新的 Canvas.
最后,我通过传递创建的位图在 dispatchDraw()
给出的主要 Canvas 上使用 drawBitmap
。
问题:
这很好用:children 有透明背景,其余部分填充白色背景。但是,当我在 children 中添加一个 DragListener
时, "cutting" 区域没有更新(而 dispatchDraw
被正确召回):换句话说, 当我拖动 child 视图时,它很好地下降了,但透明区域仍然在同一个地方。
代码:
自定义 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);
}
DragListener
和ACTION_DROP
的事件:
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
中更新值,并且它正确地更改了透明区域的坐标。
循环中children的解决方法:
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);
我在 child Views
上从 SO 上的自定义 ViewGroup
看到了很多关于 transparent
背景的问题,但是似乎没有人遇到这个问题。
背景:
我创建了一个自定义 FrameLayout
;这个容器有动态添加的视图。它的 children 应该有透明背景,但容器的另一个表面必须有背景颜色。 children 视图可以 drag'n'dropped
此容器中的任何位置。
我是做什么的:
我重写 dispatchDraw()
,创建一个 Bitmap
和一个新的 Canvas
,然后用白色背景填充新的 Canvas。
我在 children Views 上循环,从 child 的维度创建一个新的 Paint
,一个 Rect
并使用 PorterDuff.Mode.DST_OUT
清除 child的区域。对于每个 child,我将 Paint 和 Rect 添加到新的 Canvas.
最后,我通过传递创建的位图在 dispatchDraw()
给出的主要 Canvas 上使用 drawBitmap
。
问题:
这很好用:children 有透明背景,其余部分填充白色背景。但是,当我在 children 中添加一个 DragListener
时, "cutting" 区域没有更新(而 dispatchDraw
被正确召回):换句话说, 当我拖动 child 视图时,它很好地下降了,但透明区域仍然在同一个地方。
代码:
自定义 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);
}
DragListener
和ACTION_DROP
的事件:
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
中更新值,并且它正确地更改了透明区域的坐标。
循环中children的解决方法:
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);