2015-10-19 3 views
0

У меня есть ViewGroup (в частности, FrameLayout), который должен иметь эффект заливки жидкости, который я анимировал с помощью пути, который красиво показывает детские представления.Swap Android ViewGroup Детские цвета в dispatchDraw

Проблема заключается в том, что ВЫШЕ лить жидкости заполнять мне нужно показать детям с двумя цветами просмотра в обратном порядке. (Черный < -> Белый) Я не вижу способа добиться этого, просто не перебирая через растровое изображение, которое обеспечивает очень плохую копию с большим количеством псевдонимов и делает слишком медленно.

Вот сводились версия моей текущей функциональности в dispatchDraw:

@Override 
protected void dispatchDraw(Canvas canvas) 
{ 
    filter.setXfermode(null); 
    if (subBitmap == null || mLastWidth != mWidth) { 
     subBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); 
     subCanvas = new Canvas(subBitmap); 
    } 
    super.dispatchDraw(subCanvas); 
    if (mLiquidPaint == null || mLiquidPath == null || waveOval.size() == 0 || bitmapPixels == null || !mLiquidAnimator.isRunning()) { 
     canvas.drawBitmap(subBitmap, 0, 0, filter); 
     return; 
    } 

    if (revealBitmap == null || mLastWidth != mWidth) { 
     revealBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); 
     revealCanvas = new Canvas(revealBitmap); 
    } 
    if (mLastWidth != mWidth) { 
     calculateLiquid(); 
     mLastWidth = mWidth; 
    } 
    int yOffset = mFillOffset; 
    int xOffset = ellipseWidth * -1; 
    PointF firstPoint = new PointF(); 
    PointF lastPoint = new PointF(); 
    PointF nextPoint = new PointF(); 
    Pair<Integer, Float> nextWavePoint = wavePoints.get(0); 
    PointF ovalPoint = waveOval.get((nextWavePoint.first + mWaveOffset) % waveOval.size()); 
    lastPoint.set(xOffset + nextWavePoint.second + ovalPoint.x, yOffset + ovalPoint.y); 
    mLiquidPath.moveTo(lastPoint.x, lastPoint.y); 
    firstPoint.set(lastPoint); 
    for (int i = 1; i < wavePoints.size(); i++) { 
     nextWavePoint = wavePoints.get(i); 
     ovalPoint = waveOval.get((nextWavePoint.first + mWaveOffset) % waveOval.size()); 
     nextPoint.set(xOffset + nextWavePoint.second + ovalPoint.x, ovalPoint.y + yOffset); 
     mLiquidPath.lineTo(nextPoint.x, nextPoint.y); 
     lastPoint.set(nextPoint); 
    } 
    mLiquidPath.lineTo(getWidth(), lastPoint.y); 
    mLiquidPath.lineTo(getWidth(), getHeight()); 
    mLiquidPath.lineTo(0, getHeight()); 
    mLiquidPath.lineTo(firstPoint.x, firstPoint.y); 

    //This definitely draws a nice liquid path that fills from the bottom up. 
    revealCanvas.drawPath(mLiquidPath, mLiquidPaint); 
    //The next two lines successfully reveal the views underneath 
    filter.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP)); 
    revealCanvas.drawBitmap(subBitmap, 0, 0, filter); 

    filter.setXfermode(null); 
    filter.setColorFilter(null); 
    canvas.drawBitmap(revealBitmap, 0, 0, filter); 
} 

Я попробовал множество различных ColorFilters и режимов передачи безрезультатно. И дети не могут оставить фон прозрачным для меня, чтобы сделать более простой заменой цвета.

ответ

0

Наконец понял это с помощью ColorMatrixColorFilter, как указано ниже:

Для двух цветов color1 и color2 вы обменять их со следующим ColorMatrix:

float[] colorSwapMatrix = new float[] { 
    -1, 0, 0, 0, Color.red(color1) + Color.red(color2), //Red 
    0, -1, 0, 0, Color.green(color1) + Color.green(color2),//Green 
    0, 0, -1, 0, Color.blue(color1) + Color.blue(color2), //Blue 
    0, 0, 0, 1f, 0           //Alpha 
} 

Это применяется после нанесения на пути волны выше, следует:

//Draw the swapped image above the wave 
    filter.setColorFilter(new ColorMatrixColorFilter(colorSwapMatrix)); 
    filter.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)); 
    revealCanvas.drawBitmap(subBitmap, 0, 0, filter); 

    //Draw the regular image below the wave 
    filter.setColorFilter(null); 
    filter.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP)); 
    revealCanvas.drawBitmap(subBitmap, 0, 0, filter); 

    //Draw the combined image onto the canvas 
    filter.setXfermode(null); 
    filter.setColorFilter(null); 
    canvas.drawBitmap(revealBitmap, 0, 0, filter);