Android Canvas:使绘制的线在触摸时淡入淡出/alphaAnimation
我有一个 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
考虑到您要在同一视图上绘制所有三个位图,使用
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 aSurfaceView
as callingpostInvalidate
multiple times may be quite costly (unless this is running on Android 3.0+ with hardware acceleration).