2016-04-19 9 views
2

Я видел много вопросов о transparent фон на ребенке Views от пользовательского ViewGroup на SO, однако ни у кого нет такой проблемы.Рисование прозрачной области, не обновляющейся при прослушивании перетаскивания

фона:
Я создал пользовательский FrameLayout; этот контейнер имеет динамические представления. Его дети должны иметь прозрачный фон, но другая поверхность контейнера должна иметь цвет фона. Взгляды детей могут быть drag'n'dropped в любом месте этого контейнера.

Что я делаю:
я переопределить dispatchDraw(), создать Bitmap и новый Canvas, то я заполняю новый холст с белым фоном.
Я делаю петлю на детях, создаю новый Paint, размер Rect из размеров ребенка и используйте PorterDuff.Mode.DST_OUT, чтобы очистить область ребенка. Для каждого ребенка я добавляю Paint и Rect к новому холсту.
Наконец, я использую drawBitmap на основном холсте, заданный dispatchDraw(), передавая созданный растровый рисунок.

Проблема:
Это хорошо работает: дети имеют прозрачный фон, а остальное заполняется белым фоном. Однако, когда я добавляю к детям DragListener, область «разрезания» не обновляется (в то время как dispatchDraw правильно напомнён): другими словами, , когда я перетаскиваю дочерний вид, он хорошо отбрасывается, но прозрачная область все еще находится на то же место.

Код:
Обычай 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 «s событие:

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; 

Скриншоты:

Я пытался так много вещей, в отношении всех Q & А я нашел, но ничего не похоже на работу.
Любая помощь была бы очень признательна.

ответ

1

Наконец, я нашел ключ: прозрачный Paint не получает правильные значения для оси x и y после обновления.

Я думаю, что getLeft(), getTop(), и getBottom() не меняются при падении. Как ни странно, в моих журналах эти значения, похоже, обновляются. Поэтому вместо этого я попытался обновить значение в DragEvent.ACTION_DROP, используя getX() и getY(), и он правильно изменил координаты прозрачной области.

Раствор для детей в цикле:

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