0

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

问题是在液体填充线上方,我需要向孩子展示两种颜色的视图反转。(黑色<->白色)如果不简单地遍历位图,我看不到实现此目的的方法,这提供了一个非常糟糕的副本,有很多锯齿,并且渲染速度太慢。

这是我在 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 和 Transfer Modes 都无济于事。而且孩子们不能让背景透明让我做更简单的颜色替换。

4

1 回答 1

0

ColorMatrixColorFilter最后使用如下概述的 a 弄清楚了:

对于两种颜色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);
于 2015-10-20T15:33:20.187 回答