8

我正在画布上绘制一个缩放位图,并希望在指定时间淡出我的图像。

基本上,当我的角色图像越过画布的某个部分时,我需要角色图像慢慢消失(3 秒),然后页面会自动重定向到下一个 java 类。

目前,我的图像只是重定向到新的 java 类,请参阅下面的一些代码来了解我如何创建图像。

Resources res = getResources();
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, res.getDisplayMetrics());
imgSpacing = (int) px / 2;
int size = (int) ((PhoneWidth / 5) - px);

chrImg = BitmapFactory.decodeResource(getResources(), R.drawable.character);
chrImg = Bitmap.createScaledBitmap(chrImg, size, size, true);

然后在画布上 onDraw:

if(indexX == mazeFinishX && indexY == mazeFinishY)
{
    canvas.drawBitmap(finish, j * totalCellWidth, i * totalCellHeight, null);
    // As soon as the character moves over this square they are automatically re-directed to new page
    // This is where I want to fade the character image out before the re-direct
}

我在网上查看过,但是无法完全弄清楚如何让褪色效果适用于从我的游戏资源可绘制文件夹中获取的可绘制图像。谢谢

4

3 回答 3

9

如果您认为有可能在以后更改淡入淡出动画,例如缩放和/或旋转,那么您应该使用动画 XML。

但是对于快速位图淡出,您可以重复发布延迟失效消息。您可能希望将无效区域限制在字符位图所在的位置:

private static final int FADE_MILLISECONDS = 3000; // 3 second fade effect
private static final int FADE_STEP = 120;          // 120ms refresh

// Calculate our alpha step from our fade parameters
private static final int ALPHA_STEP = 255 / (FADE_MILLISECONDS / FADE_STEP);

// Initializes the alpha to 255
private Paint alphaPaint = new Paint();

// Need to keep track of the current alpha value
private int currentAlpha = 255;

@Override
protected void onDraw(Canvas canvas) {
    ...
    if(indexX == mazeFinishX && indexY == mazeFinishY) {

        // Drawing your wormhole?
        int x = j * totalCellWidth;
        int y = i * totalCellHeight;
        canvas.drawBitmap(finish, x, y, null);

        if (currentAlpha > 0) {

           // Draw your character at the current alpha value
           canvas.drawBitmap(chrImg, x, y, alphaPaint);

           // Update your alpha by a step
           alphaPaint.setAlpha(currentAlpha);
           currentAlpha -= ALPHA_STEP;

           // Assuming you hold on to the size from your createScaledBitmap call
           postInvalidateDelayed(FADE_STEP, x, y, x + size, y + size);

        } else {
           // No character draw, just reset your alpha paint
           currentAlpha = 255;
           alphaPaint.setAlpha(currentAlpha);

           // Now do your redirect
        }
    }
    ...
}

我建议将常量 FADE_MILLISECONDS 和 FADE_STEP 放入 res/integers.xml 中,这样它们就不会被硬编码。

于 2013-08-21T18:54:29.200 回答
3

我解释这一点的最佳方式是提供一个完整的自定义视图示例,您可以从中提取所需的部分。下面是一个实现这一点的视图。

public class CharacterView extends View {

    private Paint mCharacterPaint;
    private Bitmap mCharacterBitmap;
    private Transformation mTransformation;
    private AlphaAnimation mFadeOut;

    public CharacterView(Context context) {
        super(context);
        init(context);
    }

    public CharacterView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public CharacterView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context context) {
        //This would be your character image instead
        mCharacterBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);

        //We need a paint to efficiently modify the alpha
        mCharacterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //This is needed to house the current value during the animation
        mTransformation = new Transformation();
        //Construct an animation that will do all the timing math for you
        mFadeOut = new AlphaAnimation(1f, 0f);
        mFadeOut.setDuration(500);
        //Use a listener to trigger the end action
        mFadeOut.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) { }

            @Override
            public void onAnimationEnd(Animation animation) {
                //Trigger your action to change screens here.
            }

            @Override
            public void onAnimationRepeat(Animation animation) { }
        });
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            //In this example, touching the view triggers the animation
            // your code would run this sequence when the character reaches the
            // appropriate coordinates (P.S. I would not advocate putting this code
            // inside of onDraw()
            mFadeOut.start();
            mFadeOut.getTransformation(System.currentTimeMillis(), mTransformation);
            invalidate();
        }
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //...existing drawing code...

        canvas.drawBitmap(mCharacterBitmap, 0, 0, mCharacterPaint);
        if (mFadeOut.hasStarted() && !mFadeOut.hasEnded()) {
            mFadeOut.getTransformation(System.currentTimeMillis(), mTransformation);
            //Keep drawing until we are done
            mCharacterPaint.setAlpha((int)(255 * mTransformation.getAlpha()));
            invalidate();
        } else {
            //Reset the alpha if animation is canceled
            mCharacterPaint.setAlpha(255);
        }
    }
}

动态修改所绘制内容的透明度的最有效方法是使用Paint绘图将其应用到您的Canvas. 您将需要在invalidate()每个帧转换中不断地查看视图以显示动画,直到角色消失。该示例使用一个Animation对象和一个Transformation对象来处理所有时序数学,以使动画看起来确实不错。

这里的要点是您通过一些外部触发器启动动画(我不建议检查何时淡出,在onDraw()更新这些角色位置的地方可能更好。在我的示例中,为简单起见,我当视图被触摸时开始这个。

此触发器启动动画并获取初始转换值,然后invalidate()触发一个新的onDraw(). 在动画运行时,onDraw()由于invalidate()每次迭代,油漆上的 alpha 会略有下降,因此会重复。

动画完成后,它会AnimationListener为你调用 ,所以你可以在onAnimationEnd().

于 2013-08-16T16:32:38.897 回答
1
        if(indexX == mazeFinishX && indexY == mazeFinishY)
        {
            canvas.drawBitmap(finish, j * totalCellWidth, i * totalCellHeight, null);
            // As soon as the character moves over this square they are automtically re-directs to new page
            new CountDownTimer(0500, 1000) {
                @Override
                public void onTick(long millisUntilFinished) {}
                @Override
                public void onFinish() {
Paint paint = new Paint();
paint.setAlpha(25);
canvas.drawBitmap(chrImg, 0, 0, paint);
                }
            }.start();
            new CountDownTimer(0500, 1000) {
                @Override
                public void onTick(long millisUntilFinished) {}
                @Override
                public void onFinish() {
Paint paint = new Paint();
paint.setAlpha(45);
canvas.drawBitmap(chrImg, 0, 0, paint);             }
            }.start();
            new CountDownTimer(0500, 1000) {
                @Override
                public void onTick(long millisUntilFinished) {}
                @Override
                public void onFinish() {
Paint paint = new Paint();
paint.setAlpha(70);
canvas.drawBitmap(chrImg, 0, 0, paint);             }
            }.start();
            new CountDownTimer(0500, 1000) {
                @Override
                public void onTick(long millisUntilFinished) {}
                @Override
                public void onFinish() {
Paint paint = new Paint();
paint.setAlpha(100);
canvas.drawBitmap(chrImg, 0, 0, paint);             }
            }.start();
            // This is where I want to fade the character image out before the re-direct
            new CountDownTimer(3000, 1000) {

            @Override
            public void onTick(long millisUntilFinished) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onFinish() {
                // TODO Auto-generated method stub

                    Intent i = new Intent(currentclass.this, nextClass.class);
                    startActivity(i);
            }
        }.start();

    }

这将使您的位图变得透明(alpha 将为 100).. 然后在 3 秒后重定向到下一个类。

更新: 对于位图,您不能使用 .setAlpha 所以我们必须使用绘画,所以我们每次都创建一个新绘画,然后使用绘画设置位图。但如果你有一个 imageView 你可以使用 .setalpha

于 2013-08-16T15:04:41.017 回答