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
paint.setAlpha((int) alpha);
Scale mBitmap update scale property of canvas.
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:
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:
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:
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
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
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.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.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);
paint.setAlpha((int) alpha);
canvas.drawBitmap(mBitmap, X_DEFAULT_COORDINATE,
Y_DEFAULT_COORDINATE, paint);
}
History
20130905: First created.