在dispatchDraw

时间:2015-10-19 19:40:30

标签: android animation porter-duff colorfilter

我有一个ViewGroup(特别是一个FrameLayout)应该有一个流畅的填充效果,我用一个路径动画显示下面的子视图很好。

问题在于,我需要向液体填充线显示两种颜色的视图相反的孩子。 (Black< - > White)我看不到一种方法来实现这一点,而不是简单地遍历位图,这提供了一个带有大量别名的非常差的副本,并且呈现得太慢。

这是我在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和传输模式无济于事。孩子们不能让背景透明,让我做更简单的颜色替换。

1 个答案:

答案 0 :(得分:0)

最后使用如下所述的ColorMatrixColorFilter计算出来:

对于两种颜色color1color2,您可以将它们与以下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);