Android Canvas:使绘制的线在触摸时淡入淡出/alphaAnimation

发布于 2024-12-11 17:01:47 字数 3445 浏览 0 评论 0原文

我有一个 Canvas,我在 onTouchEvent() 中的点之间绘制线条。当用户对放置线条的位置做出无效选择时,我会绘制一条红线而不是黑色线。不过我希望红线在接下来的 500-1000 毫秒内消失。

我还不知道如何做到这一点,甚至不知道是否可以在 Canvas 内为单行设置动画。

我在 my: 内的 3 个不同位图之间分割了点、有效黑线和无效红线,

public void onDraw(Canvas canvas) {
    // Fade Red Line
    canvas.drawBitmap(fBitmap, 0, 0, null);
    // Lines
    canvas.drawBitmap(mBitmap, 0, 0, null);
    // Dots
    canvas.drawBitmap(iBitmap, 0, 0, null); 
}

在 onTouch 函数内是我的 drawLines()

我想知道是否可以使用 AlphaAnimation 来实现此目的,或者是否必须使用计时器系统来循环 fBitmap 以及我想要随着时间的推移淡出的红线。

有什么想法吗?

编辑:好吧,这是我一年后回来后最终解决它的方法:

我实现了一个 SurfaceView 并创建了一个线程来不断更新 Canvas。

@Override
public void run() {
    while (isRunning) {
        if (!surfaceHolder.getSurface().isValid()) {
            continue;
        }

        decreaseLineOpacity();
        drawLinesInvalid();

        /* Other things to draw*/

        Canvas canvas = surfaceHolder.lockCanvas();

        canvas.drawBitmap(fBitmap, centerPointWidth, centerPointHeight, null);
        // mBitmap is the middleground with the line that fades away.
        // and is bound to mCanvas for drawing
        canvas.drawBitmap(mBitmap, centerPointWidth, centerPointHeight, null);
        canvas.drawBitmap(iBitmap, centerPointWidth, centerPointHeight, null);

        surfaceHolder.unlockCanvasAndPost(canvas);
    }
}

然后是负责更改不透明度和绘制线条的方法,我将绘制的每条线存储在队列中,直到其不透明度达到 0,然后将其删除,这样只留下需要动画的线条:

    private void drawLinesInvalid() {
        Iterator<int[]> iterator = invalidLines.iterator();
        // Loop through each element in the Queue, delete it from the bitmap with the porter
        // duff mode to keep the transparancy of the layer. Then draw line with the given opacity
        while (iterator.hasNext()) {
            int[] invalidLine = iterator.next();
            float[] line = {invalidLine[1], invalidLine[2], invalidLine[3], invalidLine[4]};
            Xfermode originalXfermode = paint.getXfermode();
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
            mCanvas.drawLines(line, paint);
            paint.setXfermode(originalXfermode);

            paint.setColor(Color.RED);
            paint.setAlpha(invalidLine[0]);

            mCanvas.drawLines(line, paint);

        }
    }

// Call this function in the onTouch method
    private void addLineToInvalidList(float[] line) {
        // Store each line a queue with its current opacity
        int[] lineWithOpacity = new int[5];
        lineWithOpacity[0] = 250;
        lineWithOpacity[1] = (int) line[0];
        lineWithOpacity[2] = (int) line[1];
        lineWithOpacity[3] = (int) line[2];
        lineWithOpacity[4] = (int) line[3];
        invalidLines.add(lineWithOpacity);
    }

    private void decreaseLineOpacity() {
        Iterator<int[]> iterator = invalidLines.iterator();
        // Remove all lines that are finished animating (opacity = 0)
        while (iterator.hasNext()) {
            int[] line = iterator.next();
            if (line[0] == 0) {
                iterator.remove();
            }
        }

        // Decrease opacity on lines that are left
        iterator = invalidLines.iterator();
        while (iterator.hasNext()) {
            int[] line = iterator.next();
            line[0] -= 10;
        }
    }

I have a Canvas on which I am drawing lines bewteen points in a onTouchEvent(). When the user makes an invalid selection on where to place the line, I draw a red line instead of a black one. However I want the red line to fade away over the next 500-1000ms.

I haven't been able to figure out how to do it, and if it is even possible to animate a single line inside a Canvas.

I have split the dots, the valid black lines and the invalid red line(s) between 3 different bitmaps inside my:

public void onDraw(Canvas canvas) {
    // Fade Red Line
    canvas.drawBitmap(fBitmap, 0, 0, null);
    // Lines
    canvas.drawBitmap(mBitmap, 0, 0, null);
    // Dots
    canvas.drawBitmap(iBitmap, 0, 0, null); 
}

and inside my onTouch function are my drawLines().

I was wondering if I can use an AlphaAnimation for this, or if I have to use a timer system to loop over the fBitmap with the red line I want to fade out over time.

Any Ideas?

EDIT: Okay here's how I eventually solved it after coming back to it a year later:

I implemented a SurfaceView and created a thread to continuously update the Canvas.

@Override
public void run() {
    while (isRunning) {
        if (!surfaceHolder.getSurface().isValid()) {
            continue;
        }

        decreaseLineOpacity();
        drawLinesInvalid();

        /* Other things to draw*/

        Canvas canvas = surfaceHolder.lockCanvas();

        canvas.drawBitmap(fBitmap, centerPointWidth, centerPointHeight, null);
        // mBitmap is the middleground with the line that fades away.
        // and is bound to mCanvas for drawing
        canvas.drawBitmap(mBitmap, centerPointWidth, centerPointHeight, null);
        canvas.drawBitmap(iBitmap, centerPointWidth, centerPointHeight, null);

        surfaceHolder.unlockCanvasAndPost(canvas);
    }
}

And then the methods that take care of changing the opacity and drawing the line, I store each line I draw in a Queue, until it reaches an opacity of 0, and then I remove it so only the lines that need to be animated are left:

    private void drawLinesInvalid() {
        Iterator<int[]> iterator = invalidLines.iterator();
        // Loop through each element in the Queue, delete it from the bitmap with the porter
        // duff mode to keep the transparancy of the layer. Then draw line with the given opacity
        while (iterator.hasNext()) {
            int[] invalidLine = iterator.next();
            float[] line = {invalidLine[1], invalidLine[2], invalidLine[3], invalidLine[4]};
            Xfermode originalXfermode = paint.getXfermode();
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
            mCanvas.drawLines(line, paint);
            paint.setXfermode(originalXfermode);

            paint.setColor(Color.RED);
            paint.setAlpha(invalidLine[0]);

            mCanvas.drawLines(line, paint);

        }
    }

// Call this function in the onTouch method
    private void addLineToInvalidList(float[] line) {
        // Store each line a queue with its current opacity
        int[] lineWithOpacity = new int[5];
        lineWithOpacity[0] = 250;
        lineWithOpacity[1] = (int) line[0];
        lineWithOpacity[2] = (int) line[1];
        lineWithOpacity[3] = (int) line[2];
        lineWithOpacity[4] = (int) line[3];
        invalidLines.add(lineWithOpacity);
    }

    private void decreaseLineOpacity() {
        Iterator<int[]> iterator = invalidLines.iterator();
        // Remove all lines that are finished animating (opacity = 0)
        while (iterator.hasNext()) {
            int[] line = iterator.next();
            if (line[0] == 0) {
                iterator.remove();
            }
        }

        // Decrease opacity on lines that are left
        iterator = invalidLines.iterator();
        while (iterator.hasNext()) {
            int[] line = iterator.next();
            line[0] -= 10;
        }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

迷爱 2024-12-18 17:01:47

考虑到您要在同一视图上绘制所有三个位图,使用 AlphaAnimation 可能有点棘手。

我建议生成一个线程,随着时间的推移更改无效红线位图的 alpha 值(使用 Thread.sleep 休眠设定的时间间隔)。但是,为了使其表现良好,您应该考虑使用 SurfaceView,因为多次调用 postInvalidate 的成本可能相当高(除非它在具有硬件加速的 Android 3.0+ 上运行) 。

Considering you are drawing all three bitmaps on the same view, using an AlphaAnimation may be a bit tricky.

I would suggest spawning a thread that changes the alpha value of the invalid red line(s) bitmap over time (sleeping for set intervals with Thread.sleep). However, for this to perform well you should look into using a SurfaceView as calling postInvalidate multiple times may be quite costly (unless this is running on Android 3.0+ with hardware acceleration).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文