視圖動畫
視圖動畫可分爲:補間動畫、逐幀動畫。
一、補間動畫(Tweened Animation
)
分類
補間動畫:
- 平移動畫(
TranslateAnimation
) - 縮放動畫(
ScaleAnimation
) - 旋轉動畫(
RotateAnimation
) - 透明度動畫(
AlphaAnimation
)
如下圖,
可以看到途中幾個類都是Animation的子類。這4種動畫既能分開獨立實現,也可以組合實現複合動畫AnimationSet
。
缺點
- 只能實現移動、縮放、旋轉和淡入淡出這四種動畫。
- 只能改變View的顯示效果,不會改變View的屬性。
屬性動畫可以完美避免這兩缺點
優點
- 簡單易用
使用
視圖(View)動畫的實現可以通過xml來定義,也可以通過Java代碼來動態設置。對於視圖動畫,建議使用xml來定義動畫,刻度性好,而且能夠複用。
資源建立步驟:
- 在res文件下右擊New->Directory新建
anim
文件夾 anim
文件下右擊New->Animation Resource File然後彈出彈窗 ;
File name:文件名
Root element:根節點類型(set、alpha、scale、translate、rotate…)
如下,使用xml來定義:
文件目錄:res/anim/animation_test.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@[package:]anim/interpolator_resource"
android:shareInterpolator=["true" | "false"] >
<!--透明度動畫-->
<alpha
android:fromAlpha="float"
android:toAlpha="float" />
<!--縮放動畫-->
<scale
android:fromXScale="float"
android:toXScale="float"
android:fromYScale="float"
android:toYScale="float"
android:pivotX="float"
android:pivotY="float" />
<!--平移動畫-->
<translate
android:fromXDelta="float"
android:toXDelta="float"
android:fromYDelta="float"
android:toYDelta="float" />
<!--旋轉動畫-->
<rotate
android:fromDegrees="float"
android:toDegrees="float"
android:pivotX="float"
android:pivotY="float" />
<set>
...
</set>
</set>
公共屬性介紹:
動畫持續時間
- xml屬性:
android:duration="100"
- Java方法:
setDuration(100L)
- 說明: 默認值是0 (單位ms)
動畫結束後是否保留動畫前的狀態
- xml屬 性:
android:fillAfter="true"
- Java方法:
setFillAfter(boolean)
- 說明:動畫結束後是否保留動畫後的狀態,true保留動畫後狀態,false恢復原來狀態,默認值是false
動畫結束後是否保留動畫前的狀態
- xml屬性:
android:fillBefore="true"
- Java方法:
setFillBefore(boolean)
- 說明:動畫結束後是否保留動畫前的狀態,true恢復原來狀態,false保留動畫後狀態,默認值是true
動畫的變化速率 即插值器
- xml屬性:
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
- Java方法:
setInterpolator(Interpolator)
- 說明:設置動畫的變化速率 即插值器,改變動畫變換的速度,默認值是@android:anim/accelerate_decelerate_interpolator,即加速減速插值器,在動畫開始和結束的時速度較慢,中間時候加速
動畫重複執行的次數
- xml屬性:
android:repeatCount="9"
- Java方法:
setRepeatCount(int)
- 說明:設置動畫重複執行的次數,默認值是0
動畫重複的模式
- xml屬性:
android:repeatMode="reverse"
- Java方法:
setRepeatMode(int)
- 說明:設置動畫重複模式,其值有restart(1):順序播放,reverse(2):重複的時候逆向播放
開始的延遲的時間
- xml屬性:
android:startOffset="0"
- Java方法:
setStartOffset(long)
- 說明:設置開始的延遲的時間(單位ms),默認值是0
加載資源文件動畫
Animation animation = AnimationUtils.loadAnimation(this, R.anim.test_alpha);
爲View
添加動畫
view.setAnimation(animation);
設置動畫監聽
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
//動畫開始時回掉
}
@Override
public void onAnimationEnd(Animation animation) {
//動畫結束時回掉(動畫最終結束)
}
@Override
public void onAnimationRepeat(Animation animation) {
//動畫重複時回掉
}
});
啓動動畫
animation.start();
//或
view.startAnimation(animation);
結束動畫
animation.cancel();
詳細講解各動畫屬性
AlphaAnimation
作用:透明度動畫,改變視圖整體透明度,透明度值由1~0,從可見到不可見的變化。
xml實現
步驟:在anim
文件,右擊new->Android Resource File ,文件名:alpha_test
,根節點:alpha
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="2000">
</alpha>
各屬性含義:
android:fromAlpha
: 表示透明度的起始值,這裏設置爲0.0,表示完全透明,取值範圍0~1;android:toAlpha
:表示透明度的結束值,這裏設置爲1.0,表示完全不透明,取值範圍0~1;android:duration
:表示動畫持續的時間,這裏設置爲2000,單位是毫秒;
Java代碼中使用xml:使用AnimationUtils類的靜態方法loadAnimation()來加載XML文件,得到一個Animation對象,如下:
Animation animation = AnimationUtils.loadAnimation(this, R.anim.alpha);
mImage.startAnimation(animation);
Java實現
AlphaAnimation alphaAnimation = new AlphaAnimation(0f, 1f);
alphaAnimation.setDuration(3000);
mImage.startAnimation(alphaAnimation);
構造方法:
- 通過加載資源文件
/** * Constructor used when an AlphaAnimation is loaded from a resource. * * @param context Application context to use * @param attrs Attribute set from which to read values */ public AlphaAnimation(Context context, AttributeSet attrs) { super(context, attrs); }
- 通過代碼構建動畫
/** * Constructor to use when building an AlphaAnimation from code * * @param fromAlpha Starting alpha value for the animation, where 1.0 means * fully opaque and 0.0 means fully transparent. * @param toAlpha Ending alpha value for the animation. */ public AlphaAnimation(float fromAlpha, float toAlpha) { mFromAlpha = fromAlpha; mToAlpha = toAlpha; }
ScaleAnimation
縮放動畫,需要一個座標點來,即軸點,實現以不同的軸點縮放效果,因此需要先指定pivotX
、pivotY
確定軸座標。默認情況下,從對象View
的左上角開始縮放。
xml實現
該動畫通過標籤<scale/>
實現的,如下:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0">
</scale>
各屬性如下:
android:fromXScale
: 動畫開始時,水平方向縮放係數。android:fromYScale
: 動畫開始時,垂直方向縮放係數。android:toXScale
: 動畫結束時,水平方向縮放係數。android:toYScale
:動畫結束時,垂直方向縮放係數。android:pivotX
:縮放軸點的X座標(其值可以爲:數值、百分數、百分數p),例如:如50表示以當前View左上角座標加50px爲初始點、50%表示以當前View的左上角加上當前View寬高的50%做爲初始點、50%p表示以當前View的左上角加上父控件寬高的50%做爲初始點)。android:pivotY
:縮放軸點的Y座標,規律同pivotX。
java實現
需要使用Animation的子類ScaleAnimation來實現,代碼如下:
ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setDuration(3000);
mImage.startAnimation(scaleAnimation);
構造方法:
// 1.
/**
* Constructor used when a ScaleAnimation is loaded from a resource.
*
* @param context Application context to use
* @param attrs Attribute set from which to read values
*/
public ScaleAnimation(Context context, AttributeSet attrs) {
super(context, attrs);
}
// 2.
/**
* Constructor to use when building a ScaleAnimation from code
*
* @param fromX Horizontal scaling factor to apply at the start of the
* animation
* @param toX Horizontal scaling factor to apply at the end of the animation
* @param fromY Vertical scaling factor to apply at the start of the
* animation
* @param toY Vertical scaling factor to apply at the end of the animation
*/
public ScaleAnimation(float fromX, float toX, float fromY, float toY) {
mResources = null;
mFromX = fromX;
mToX = toX;
mFromY = fromY;
mToY = toY;
mPivotX = 0;
mPivotY = 0;
}
//3.
/**
* Constructor to use when building a ScaleAnimation from code
*
* @param fromX Horizontal scaling factor to apply at the start of the
* animation
* @param toX Horizontal scaling factor to apply at the end of the animation
* @param fromY Vertical scaling factor to apply at the start of the
* animation
* @param toY Vertical scaling factor to apply at the end of the animation
* @param pivotX The X coordinate of the point about which the object is
* being scaled, specified as an absolute number where 0 is the left
* edge. (This point remains fixed while the object changes size.)
* @param pivotY The Y coordinate of the point about which the object is
* being scaled, specified as an absolute number where 0 is the top
* edge. (This point remains fixed while the object changes size.)
*/
public ScaleAnimation(float fromX, float toX, float fromY, float toY,
float pivotX, float pivotY) {
}
// 4.
/**
* Constructor to use when building a ScaleAnimation from code
*
* @param fromX Horizontal scaling factor to apply at the start of the
* animation
* @param toX Horizontal scaling factor to apply at the end of the animation
* @param fromY Vertical scaling factor to apply at the start of the
* animation
* @param toY Vertical scaling factor to apply at the end of the animation
* @param pivotXType Specifies how pivotXValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param pivotXValue The X coordinate of the point about which the object
* is being scaled, specified as an absolute number where 0 is the
* left edge. (This point remains fixed while the object changes
* size.) This value can either be an absolute number if pivotXType
* is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
* @param pivotYType Specifies how pivotYValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param pivotYValue The Y coordinate of the point about which the object
* is being scaled, specified as an absolute number where 0 is the
* top edge. (This point remains fixed while the object changes
* size.) This value can either be an absolute number if pivotYType
* is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
*/
public ScaleAnimation(float fromX, float toX, float fromY, float toY,
int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) {
}
RotateAnimation
旋轉動畫,與縮放動畫較爲相似,也需要一個軸點來實現旋轉。默認情況下,從對象view的左上角開始旋轉,也即是相對於當前view座標爲(0,0)位置。
在xml實現
該動畫是通過標籤實現的,實現代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:pivotX="50%"
android:pivotY="50%"
android:fromDegrees="0"
android:toDegrees="90">
</rotate>
各屬性含義:
android:pivotX
:旋轉軸點的X座標(其值可以爲:數值、百分數、百分數p),例如:如50表示以當前View左上角座標加50px爲初始點、50%表示以當前View的左上角加上當前View寬高的50%做爲初始點、50%p表示以當前View的左上角加上父控件寬高的50%做爲初始點)。android:pivotY
:旋轉軸點的Y座標,規律同android:pivotX
。android:fromDegrees
:旋轉開始的角度,其值可以爲正負。android:toDegrees
: 旋轉結束的角度,其值可以爲正負。- ps:
toDegrees
-fromDegrees
> 0,則順時針旋轉;否則,逆時針旋轉。
java實現
需要使用Animation的子類RotateAnimation 來實現,代碼如下:
RotateAnimation rotateAnimation = new RotateAnimation(0,180);
rotateAnimation.setDuration(3000);
mImage.startAnimation(rotateAnimation);
構造方法:
// 1.
/**
* Constructor used when a RotateAnimation is loaded from a resource.
*
* @param context Application context to use
* @param attrs Attribute set from which to read values
*/
public RotateAnimation(Context context, AttributeSet attrs) {
super(context, attrs);
}
// 2.
/**
* Constructor to use when building a RotateAnimation from code.
* Default pivotX/pivotY point is (0,0).
*
* @param fromDegrees Rotation offset to apply at the start of the
* animation.
*
* @param toDegrees Rotation offset to apply at the end of the animation.
*/
public RotateAnimation(float fromDegrees, float toDegrees) {
}
// 3.
/**
* Constructor to use when building a RotateAnimation from code
*
* @param fromDegrees Rotation offset to apply at the start of the
* animation.
*
* @param toDegrees Rotation offset to apply at the end of the animation.
*
* @param pivotX The X coordinate of the point about which the object is
* being rotated, specified as an absolute number where 0 is the left
* edge.
* @param pivotY The Y coordinate of the point about which the object is
* being rotated, specified as an absolute number where 0 is the top
* edge.
*/
public RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mPivotXType = ABSOLUTE;
mPivotYType = ABSOLUTE;
mPivotXValue = pivotX;
mPivotYValue = pivotY;
initializePivotPoint();
}
//4.
/**
* Constructor to use when building a RotateAnimation from code
*
* @param fromDegrees Rotation offset to apply at the start of the
* animation.
*
* @param toDegrees Rotation offset to apply at the end of the animation.
*
* @param pivotXType Specifies how pivotXValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param pivotXValue The X coordinate of the point about which the object
* is being rotated, specified as an absolute number where 0 is the
* left edge. This value can either be an absolute number if
* pivotXType is ABSOLUTE, or a percentage (where 1.0 is 100%)
* otherwise.
* @param pivotYType Specifies how pivotYValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param pivotYValue The Y coordinate of the point about which the object
* is being rotated, specified as an absolute number where 0 is the
* top edge. This value can either be an absolute number if
* pivotYType is ABSOLUTE, or a percentage (where 1.0 is 100%)
* otherwise.
*/
public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,
int pivotYType, float pivotYValue) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mPivotXValue = pivotXValue;
mPivotXType = pivotXType;
mPivotYValue = pivotYValue;
mPivotYType = pivotYType;
initializePivotPoint();
}
TranslateAnimation
平移動畫,實現視圖垂直/水平方向位移變化,指定開始的位置,和結束的位置即可。
xml實現:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:duration="3000"
android:fromXDelta="50%"
android:fromYDelta="50%"
android:toXDelta="50%p"
android:toYDelta="50%p">
</translate>
各屬性含義:
android:fromXDelta
: 平移開始X方向座標(其值可以爲:數值、百分數、百分數p,且多可以爲正負),其值含義與android:pivotX
類似。android:fromYDelta
:平移開始Y方向座標(其值可以爲:數值、百分數、百分數p,且多可以爲正負),其值含義與android:pivotY
類似。android:toXDelta
:平移結束X方向座標(其值可以爲:數值、百分數、百分數p,且多可以爲正負),其值含義與android:pivotX
類似。android:toYDelta
:平移結束Y方向座標(其值可以爲:數值、百分數、百分數p,且多可以爲正負),其值含義與android:pivotY
類似。
java實現
需要使用Animation的子類TranslateAnimation來實現,代碼如下:
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_PARENT,0,Animation.RELATIVE_TO_PARENT,0.5f);
translateAnimation.setDuration(3000);
translateAnimation.setFillAfter(true);
mImage.startAnimation(translateAnimation);
構造函數:
// 1.
/**
* Constructor used when a TranslateAnimation is loaded from a resource.
*
* @param context Application context to use
* @param attrs Attribute set from which to read values
*/
public TranslateAnimation(Context context, AttributeSet attrs) {
super(context, attrs);
}
// 2.
/**
* Constructor to use when building a TranslateAnimation from code
*
* @param fromXDelta Change in X coordinate to apply at the start of the
* animation
* @param toXDelta Change in X coordinate to apply at the end of the
* animation
* @param fromYDelta Change in Y coordinate to apply at the start of the
* animation
* @param toYDelta Change in Y coordinate to apply at the end of the
* animation
*/
public TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta) {
mFromXValue = fromXDelta;
mToXValue = toXDelta;
mFromYValue = fromYDelta;
mToYValue = toYDelta;
mFromXType = ABSOLUTE;
mToXType = ABSOLUTE;
mFromYType = ABSOLUTE;
mToYType = ABSOLUTE;
}
// 3.
/**
* Constructor to use when building a TranslateAnimation from code
*
* @param fromXType Specifies how fromXValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param fromXValue Change in X coordinate to apply at the start of the
* animation. This value can either be an absolute number if fromXType
* is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
* @param toXType Specifies how toXValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param toXValue Change in X coordinate to apply at the end of the
* animation. This value can either be an absolute number if toXType
* is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
* @param fromYType Specifies how fromYValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param fromYValue Change in Y coordinate to apply at the start of the
* animation. This value can either be an absolute number if fromYType
* is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
* @param toYType Specifies how toYValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param toYValue Change in Y coordinate to apply at the end of the
* animation. This value can either be an absolute number if toYType
* is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
*/
public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue,
int fromYType, float fromYValue, int toYType, float toYValue) {
mFromXValue = fromXValue;
mToXValue = toXValue;
mFromYValue = fromYValue;
mToYValue = toYValue;
mFromXType = fromXType;
mToXType = toXType;
mFromYType = fromYType;
mToYType = toYType;
}
AnimationSet
集合動畫,如果單一的動畫太過於單調,那麼就可以將這些單一的動畫組合成個性酷炫的動畫,同時指定播放的順序,並且集合裏面可以再包含集合。但注意的是,在集合設置的屬性對該標籤下的所有子控件都產生影響。
xml實現:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<scale
android:duration="2000"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0"
android:toYScale="0"/>
<set
android:duration="2000"
android:interpolator="@android:anim/decelerate_interpolator"
android:shareInterpolator="true"
android:startOffset="2000">
<scale
android:fromXScale="0"
android:fromYScale="0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1"/>
<rotate
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="180"/>
</set>
</set>
屬性含義:
android:shareInterpolator
:子元素是否共享插值器,值爲true,表示共同使用;值爲false,表示不共享
其餘屬性多和其他類似,android:startOffset
:設置需要設置播放的順序。
java實現
AnimationSet animationSet1 = new AnimationSet(false);//一級集合
ScaleAnimation scaleAnimation1 = new ScaleAnimation(1, 1.4f, 1, 1.4f, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
AnimationSet animationSet2 = new AnimationSet(true);//二級集合
ScaleAnimation scaleAnimation2 = new ScaleAnimation(1.4f, 0, 1.4f, 0, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
RotateAnimation rotateAnimation = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
animationSet2.addAnimation(scaleAnimation2);
animationSet2.addAnimation(rotateAnimation);
animationSet2.setInterpolator(new DecelerateInterpolator());
animationSet2.setDuration(2000);
animationSet2.setStartOffset(2000);
animationSet1.addAnimation(scaleAnimation1);
animationSet1.addAnimation(animationSet2);
animationSet1.setInterpolator(new AccelerateDecelerateInterpolator());
animationSet1.setDuration(2000);
mImage.startAnimation(animationSet1);
構造函數:
// 1.
/**
* Constructor used when an AnimationSet is loaded from a resource.
*
* @param context Application context to use
* @param attrs Attribute set from which to read values
*/
public AnimationSet(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a =
context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AnimationSet);
setFlag(PROPERTY_SHARE_INTERPOLATOR_MASK,
a.getBoolean(com.android.internal.R.styleable.AnimationSet_shareInterpolator, true));
init();
if (context.getApplicationInfo().targetSdkVersion >=
Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
if (a.hasValue(com.android.internal.R.styleable.AnimationSet_duration)) {
mFlags |= PROPERTY_DURATION_MASK;
}
if (a.hasValue(com.android.internal.R.styleable.AnimationSet_fillBefore)) {
mFlags |= PROPERTY_FILL_BEFORE_MASK;
}
if (a.hasValue(com.android.internal.R.styleable.AnimationSet_fillAfter)) {
mFlags |= PROPERTY_FILL_AFTER_MASK;
}
if (a.hasValue(com.android.internal.R.styleable.AnimationSet_repeatMode)) {
mFlags |= PROPERTY_REPEAT_MODE_MASK;
}
if (a.hasValue(com.android.internal.R.styleable.AnimationSet_startOffset)) {
mFlags |= PROPERTY_START_OFFSET_MASK;
}
}
a.recycle();
}
// 2.
/**
* Constructor to use when building an AnimationSet from code
*
* @param shareInterpolator Pass true if all of the animations in this set
* should use the interpolator associated with this AnimationSet.
* Pass false if each animation should use its own interpolator.
*/
public AnimationSet(boolean shareInterpolator) {
setFlag(PROPERTY_SHARE_INTERPOLATOR_MASK, shareInterpolator);
init();
}
問題
你是否真正的明白 pivotX 的含義?
軸點座標值pivotX,pivotY,有三種表達方式:在xml文件,其值有3種類型:數值、百分數、百分數p;在java代碼中,其值要根據,三種座標類型(前方有介紹)來確定。
一般,對於表達方式的第一種、第二種,應該是比較常用的,而且也是比較好理解的,也比較直觀。那麼問題來了:
提出問題:
如果是使用第三種,相對於父控件定位,你是否能夠準確找到軸點位置?是否知道其真正的含義?
猜想:
pivotX = 50%,那麼軸點就在該控件(沒有覆蓋整個屏幕)的中間位置;pivotX = 50%p,那麼中心點相對於父控件(覆蓋了整個屏幕)就是屏幕的中間點。
對於這個想法,我…我…我…剛開始是這樣子想的…
實踐:
我們用平移動畫來實踐,保留動畫結束的幀,將其參數設置爲:
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0.5f, Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0.5f);
從相當於父控件的(0,0) 移動到 父控件的(50%,50%),但實際效果是這樣子的,與猜想不符:
具體效果請看
探索:
我們可以點進去看TranslateAnimation ,可以發現:
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mFromXDelta = resolveSize(mFromXType, mFromXValue, width, parentWidth);
mToXDelta = resolveSize(mToXType, mToXValue, width, parentWidth);
mFromYDelta = resolveSize(mFromYType, mFromYValue, height, parentHeight);
mToYDelta = resolveSize(mToYType, mToYValue, height, parentHeight);
}
// 然後再看resolveSize()方法
protected float resolveSize(int type, float value, int size, int parentSize) {
switch (type) {
case ABSOLUTE:
return value;
case RELATIVE_TO_SELF:
return size * value;
case RELATIVE_TO_PARENT:
return parentSize * value;
default:
return value;
}
}
// 也許,看到這裏,反而覺得猜想沒有錯。其實動畫真正的實現是在這裏:
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float dx = mFromXDelta;
float dy = mFromYDelta;
if (mFromXDelta != mToXDelta) {
dx = mFromXDelta + ((mToXDelta - mFromXDelta) * interpolatedTime);
}
if (mFromYDelta != mToYDelta) {
dy = mFromYDelta + ((mToYDelta - mFromYDelta) * interpolatedTime);
}
t.getMatrix().setTranslate(dx, dy);
}
這裏,我們發現,動畫需要繪製的軌跡是dx = mToXDelta ,dy = mToYDelta ,這個值是相對於該控件 需要變化的距離,而不是最終的位置,那麼最終猜想:
如果該控件剛好位於屏幕的左上角,則mToXValue就是動畫結束的位置;
如果該控件不在屏幕的左上角,則最終動畫後的座標需要加上該控件這個座標;
最後用表達式表示:
toXValue = fromXType + dx
;
toYType = fromYValue + dy
;
二、幀動畫(Frame Animation
)
實現
- 在res文件下右擊New->Directory新建
drawable
文件夾 anim
文件下右擊New->Drawable Resource File然後彈出彈窗 ;
File name:文件名
Root element:根節點類型(選擇animation-list
)
創建資源xml代碼(res/drawable/frame_view.xml
)
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/sign_icon_1"
android:duration="50" />
<item
android:drawable="@drawable/sign_icon_2"
android:duration="50" />
<item
android:drawable="@drawable/sign_icon_3"
android:duration="50" />
<item
android:drawable="@drawable/sign_icon_4"
android:duration="50" />
</animation-list>
使用(res/layout/activity_frame_animation.xml
)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<ImageView
android:id="@+id/image"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/frame_view" />
</LinearLayout>
開啓動畫:
ImageView imageView = findViewById(R.id.image);
AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getDrawable();
if (animationDrawable != null) {
animationDrawable.start();
}