Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Mobile / Android

Animation with SurfaceView

4.40/5 (5 votes)
5 Sep 2013CPOL2 min read 35.6K   1.2K  
This article give a solution to develop Animation by using Canvas, Paint and SurfaceView

Introduction

In fact you maybe got some requirement likes that: make a list auto scroll, the center image will be auto scale up...With the requirements like that, it seems there is no View in Android can be applied to resolve, and you must customize by your self.

Normally, the most importance point I think almost developer must resolve is View animation.

Today, I will guide a solution which is used to customize View in Android development, it is Animation in SurfaceView. I also wrote some article about it, such as, Half Circle List View or Auto Slide List View,...

This article is only my thinking, maybe not a best solution. But I hope I can bring to you a way, to continue with Android customize View.

Background

A lot of developers think that, SurfaceView is really special in Android. No, it is a normal View only. The different point is it can be drawn in background thread (onDraw() of View must be executed in UI thread). Summary, the way to executed animation will executed in a thread run continuously 2 functions below

  • Update the view's properties coordinate, alpha, scale.
  • Draw view with updated properties.

To do it, using Canvas and Paint. I will give an example with Bitmap for easy in thinking with below code:

canvas.drawBitmap(mBitmap, x, y, paint);

Translate mBitmap, update x, y

Fade out or fade in mBitmap, update alpha of paint

Java
paint.setAlpha((int) alpha);  

Scale mBitmap update scale property of canvas.

Java
canvas.scale(scaleValue, 1, mBitmap.getWidth() / 2, mBitmap.getHeight() / 2);  

Rotate mBitmap, you can update matrix value. Please refer hererefer here for more detail.

How about animation?

Base on idea about, if we can give a formula to update mBitmap properties, we can execute animation. Please thinking via simple sample:

Suppose that, from time t1 to time t2, view is translated from x1 to x2. What is the coordinate of view in time t? The formula will be: x = x1 + t * (x2-x1) / (t2-t1)

Using the code

Animation.java

Base on idea above, I made a simple Animation class which is used to calculate the current value, with below properties:

  • mStartValue: The beginning value when animation starting.
  • mEndValue: The final value when animation ending.
  • mDuration: The duration to change value from mStartValue to mEndValue.
  • mStartTime: The time animation starting. At the time animation is started, it is got by System.currentTimeMillis().
  • mEndTime: The time animation ending. mEndTime = mStartTime + mDuration.
The method to get the current value at specified time will be:
Java
public float getCurrentValue(long currentTime) {
   float currentValue = mStartValue + (currentTime)
                * (mEndValue - mStartValue) / mDuration;
   if (currentTime > mEndTime) {
           currentValue = mEndValue;
   }
   return currentValue; 
}   

Extends Animation.java, we have AlphaAnimation, ScaleXAnimation, ScaleYAnimation, TranslateXAnimation, TranslateYAnimation.

To translate bitmap from [x = 0] to [x = screen width] in 3 seconds you can make TranslateXAnimation:

Java
animation = new TranslateXAnimation();
animation.mDuration = 3000;
animation.mStartTime = System.currentTimeMillis();
animation.mEndTime = System.currentTimeMillis() + 3000;
animation.mStartValue = 0;
animation.mEndValue = SCREEN_WIDTH;   

To translate bitmap from [y = 0] to [x = screen height] in 3 seconds you can make TranslateYAnimation:

Java
animation = new TranslateYAnimation();
animation.mDuration = 3000;
animation.mStartTime = System.currentTimeMillis();
animation.mEndTime = System.currentTimeMillis() + 3000;
animation.mStartValue = 0;
animation.mEndValue = SCREEN_HEIGHT;  

To fade in bitmap from alpha = 0 to alpha = 255, make AlphaAnimation

Java
animation = new AlphaAnimation();
animation.mDuration = 3000;
animation.mStartTime = System.currentTimeMillis();
animation.mEndTime = System.currentTimeMillis() + 3000;
animation.mStartValue = 0;
animation.mEndValue = 255;  

To draw bitmap in SurfaceView, base on the animation type to apply the way in Background

Java
if (animation.mType == Type.TranslateX) {
                float currentX = animation.getCurrentValue(System
                        .currentTimeMillis() - animation.mStartTime);
                canvas.drawBitmap(mBitmap, currentX, Y_DEFAULT_COORDINATE,
                        paint);
            } else if (animation.mType == Type.TranslateY) {
                float currentY = animation.getCurrentValue(System
                        .currentTimeMillis() - animation.mStartTime);
                canvas.drawBitmap(mBitmap, X_DEFAULT_COORDINATE, currentY,
                        paint);
            } else if (animation.mType == Type.ScaleX) {
                float currentY = animation.getCurrentValue(System
                        .currentTimeMillis() - animation.mStartTime);
                // canvas.drawBitmap(mBitmap, X_DEFAULT_COORDINATE, currentY,
                // paint);
                canvas.scale(currentY, 1, mBitmap.getWidth() / 2,
                        mBitmap.getHeight() / 2);
                canvas.drawBitmap(mBitmap, X_DEFAULT_COORDINATE,
                        Y_DEFAULT_COORDINATE, paint);
            } else if (animation.mType == Type.ScaleY) {
                float currentY = animation.getCurrentValue(System
                        .currentTimeMillis() - animation.mStartTime);
                // canvas.drawBitmap(mBitmap, X_DEFAULT_COORDINATE, currentY,
                // paint);
                canvas.scale(1, currentY, mBitmap.getWidth() / 2,
                        mBitmap.getHeight() / 2);
                canvas.drawBitmap(mBitmap, X_DEFAULT_COORDINATE,
                        Y_DEFAULT_COORDINATE, paint);
            } else if (animation.mType == Type.Alpha) {
                float alpha = animation.getCurrentValue(System
                        .currentTimeMillis() - animation.mStartTime);
                // canvas.drawBitmap(mBitmap, X_DEFAULT_COORDINATE, currentY,
                // paint);
                paint.setAlpha((int) alpha);
                canvas.drawBitmap(mBitmap, X_DEFAULT_COORDINATE,
                        Y_DEFAULT_COORDINATE, paint);
            }  

History 

20130905: First created.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)