0

我正在创建一个绘图应用程序,我希望用户可以使用的画笔具有以下效果:

示例效果

目前,为了实现这种效果,我正在绘制 5 个单独的路径,每个路径具有相同的 X 值但 Y 偏移量很小,并且每个路径都有一个 BlurMaskFilter。这是 PaintBrush 类的代码:

public PaintBrush(int initColor, int initSize) {
    strokeRadius = ((10 * initSize) + 20) / 2;
    currentColor = initColor
    setupPaths();
}

private void setupPaths(){
    paths = new Path[5];
    paints = new Paint[5];
    for (int i = 0; i < 5; i++){
        paths[i] = new Path();
        Paint curPaint =  new Paint();
        curPaint.setColor(currentColor);
        curPaint.setAntiAlias(true);
        curPaint.setDither(true);
        curPaint.setStyle(Paint.Style.STROKE);
        curPaint.setStrokeJoin(Paint.Join.ROUND);
        curPaint.setStrokeCap(Paint.Cap.ROUND);
        paints[i] = curPaint;
    }
    Paint paint1 = paints[0];
    paint1.setStrokeWidth(strokeRadius / 3);
    paint1.setMaskFilter(new BlurMaskFilter(Math.max(strokeRadius / 5, 1), BlurMaskFilter.Blur.NORMAL));
    Paint paint2 = paints[1];
    paint2.setStrokeWidth(strokeRadius / 6);
    paint2.setMaskFilter(new BlurMaskFilter(Math.max(strokeRadius / 7, 1), BlurMaskFilter.Blur.NORMAL));
    Paint paint3 = paints[2];
    paint3.setStrokeWidth(strokeRadius / 5);
    paint3.setMaskFilter(new BlurMaskFilter(Math.max(strokeRadius / 7, 1), BlurMaskFilter.Blur.NORMAL));
    Paint paint4 = paints[3];
    paint4.setStrokeWidth(strokeRadius / 3);
    paint4.setMaskFilter(new BlurMaskFilter(Math.max(strokeRadius / 4, 1), BlurMaskFilter.Blur.NORMAL));
    Paint paint5 = paints[4];
    paint5.setStrokeWidth(strokeRadius / 4);
    paint5.setMaskFilter(new BlurMaskFilter(Math.max(strokeRadius / 4, 1), BlurMaskFilter.Blur.NORMAL));
}

public void drawBrush(Canvas canvas){
    for (int i = 0; i < 5; i++) {
        canvas.drawPath(paths[i], paints[i]);
    }
}



public void startStroke(float x, float y){
    paths[0].moveTo(x, y - (strokeRadius * 4 / 6));
    paths[1].moveTo(x, y - (strokeRadius / 3));
    paths[2].moveTo(x, y - (strokeRadius / 8));
    paths[3].moveTo(x, y + (strokeRadius / 3));
    paths[4].moveTo(x, y + (strokeRadius * 3 / 4));
    prevX = x;
    prevY = y;
}

public void moveStroke(float x, float y){
    float dx = Math.abs(x - prevX);
    float dy = Math.abs(y - prevY);
    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
        paths[0].quadTo(prevX, prevY - (strokeRadius * 4 / 6), (x + prevX) / 2, ((y + prevY) / 2) - (strokeRadius * 4 / 6));
        paths[1].quadTo(prevX, prevY - (strokeRadius / 3), (x + prevX) / 2, ((y + prevY) / 2) - (strokeRadius / 3));
        paths[2].quadTo(prevX, prevY - (strokeRadius / 8), (x + prevX) / 2, ((y + prevY) / 2) - (strokeRadius / 8));
        paths[3].quadTo(prevX, prevY + (strokeRadius / 3), (x + prevX) / 2, ((y + prevY) / 2) + (strokeRadius / 3));
        paths[4].quadTo(prevX, prevY + (strokeRadius * 3 / 4), (x + prevX) / 2, ((y + prevY) / 2) + (strokeRadius * 3 / 4));
    }
    prevX = x;
    prevY = y;
}

public void endStroke(Canvas canvas){
    drawBrush(canvas);
    paths[0].reset();
    paths[1].reset();
    paths[2].reset();
    paths[3].reset();
    paths[4].reset();
}

以及自定义视图的代码:

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(drawingCanvas, 0, 0, canvasPaint);
    currentBrush.drawBrush(canvas);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (!activity.isPaused()) {
        float touchX = event.getX();
        float touchY = event.getY();
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                currentBrush.startStroke(touchX, touchY);
                break;
            case MotionEvent.ACTION_MOVE:
                currentBrush.moveStroke(touchX, touchY);
                break;
            case MotionEvent.ACTION_UP:
                currentBrush.endStroke(touchX, touchY, drawingCanvas);
                break;
            default:
                return false;
        }
        invalidate();
    }
    return true;
}

我知道 BlurMaskFilter 与硬件加速不兼容,因此在我的主要活动中,我有以下代码:

drawingView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

这段代码可以工作,但是,在禁用硬件加速的情况下,我的绘图活动对性能造成了巨大的(并且不可接受的)影响;它的延迟非常明显,尤其是当路径变长时。我的问题是:有没有一种方法可以在不使用硬件加速的情况下提高性能,足以减少延迟?如果没有,有没有办法以与硬件加速兼容的方式模拟同样的效果?

4

1 回答 1

0

保留整个屏幕大小的位图。保留手指移动过的所有点的列表。从上一个接触点到最后一个接触点的距离有一些最小阈值。您基本上将绘图运动分解为点列表。

现在,每次手指移动时,找到自上次处理触摸事件以来更改的区域的边界矩形,清除此矩形,并仅使用您的 drawPath 重绘列表中此矩形中的行。

于 2016-02-28T18:38:59.860 回答