編輯:關於Android編程
public class MainActivity extends Activity { private Button mButton; private ImageView mImageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); mButton = (Button) findViewById(R.id.button); mImageView = (ImageView) findViewById(R.id.imageview); mButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { playAnim(); } }); mImageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { showToast(); } }); } /** * 播放動畫 */ protected void playAnim() { TranslateAnimation ta = new TranslateAnimation(0.0f, 200.0f, 0.0f, 0.0f); ta.setDuration(1000); ta.setFillAfter(true); mImageView.startAnimation(ta); } protected void showToast() { Toast.makeText(MainActivity.this, Hello, Toast.LENGTH_SHORT).show(); } }看到運行效果了吧,我們給ImageView的小機器人設置了點擊事件並且彈出Toast了,當我們點擊Button時,ImageView上的平移動畫被執行了,並且平移到了指定的位置(200px),然而我們在此時的ImageView上點擊時,並沒有彈出Toast提示,也就是說點擊的位置不在那裡,當我回頭再次點擊ImageView最初的位置時,Toast又被show了出來,這是不是很“詭異”?是的,上面的小例子足以說明,傳統的Animaion動畫只能改變動態視覺效果的動畫,並不能真實的去改變一個View的屬性(位置等)。而且,傳統的Animation動畫是通過不停的調用onDraw方法去繪制而完成的效果,這樣的實現方式很消耗資源(cpu)的。
protected void playAnim() { ObjectAnimator.ofFloat(mImageView, translationX, 0.0f, 200.0f).setDuration(1000).start(); }運行效果如上圖所示。對比上面的那幅圖看,發現當屬性動畫執行後,不但從視覺上改變了ImageView的位置,而且ImageView上的點擊事件的位置也跟著變化了,說明使用屬性動畫的View,實際上是真實的改變了一個View的屬性的。 從上面的一行代碼中,可以發現屬性動畫使用上是非常簡單的,ObjectAnimator中的ofFloat方法實際上是static方法,而且返回值還是一個ObjectAnimator對象。ofFloat的參數也很簡單,第1個參數是指定需要執行動畫的view,第2個參數是動畫模式,第三個參數是可變的數組,這裡需要描述動畫的初始位置和終點位置的坐標。 除了上面例子的中的translationX屬性,還可以指定translationY屬性,表示ImageView沿著Y軸的方向平移,然後我們也可以指定X或者Y,那麼translationX和X或者translationY和Y的區別,就是translationX是指定了ImageView在X軸上的偏移量,而單純的指定X表示ImageView被移動到指定的X軸上的位置,這點跟View的scrollTo和scrollBy方法有點類似。此外除了平移之外,還可以指定動畫的模式有: translationX、translationY rotation、rotationX、rotationY scaleX、scaleY X、Y alpha
ObjectAnimator繼承自ValueAnimator,要指定一個對象及該對象的一個屬性,當屬性值計算完成時自動設置為該對象的相應屬性,即完成了Property Animation的全部兩步操作。實際應用中一般都會用ObjectAnimator來改變某一對象的某一屬性,但用ObjectAnimator有一定的限制,要想使用ObjectAnimator,應該滿足以下條件:
對象應該有一個setter函數:set如果上述條件不滿足,則不能用ObjectAnimator,應用ValueAnimator代替。
protected void playAnim() { PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat(translationX,0.0f, 200.0f); PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat(translationY,0.0f, 200.0f); PropertyValuesHolder p3 = PropertyValuesHolder.ofFloat(rotation,0.0f, 360.0f); ObjectAnimator.ofPropertyValuesHolder(mImageView, p1, p2, p3).setDuration(2000).start(); }
protected void playAnim() { Animator animator1 = ObjectAnimator.ofFloat(mImageView, translationX,0.0f, 200.0f); Animator animator2 = ObjectAnimator.ofFloat(mImageView, translationY,0.0f, 200.0f); Animator animator3 = ObjectAnimator.ofFloat(mImageView, rotation,0.0f, 360.0f); AnimatorSet set = new AnimatorSet(); set.playTogether(animator1, animator2, animator3); set.setDuration(2000); set.start(); }
AnimationSet提供了一個把多個動畫組合成一個組合的機制,並可設置組中動畫的時序關系,如同時播放,順序播放等。
以下例子同時應用5個動畫:
播放anim1;同時播放anim2,anim3,anim4;播放anim5。AnimatorSet bouncer = new AnimatorSet(); bouncer.play(anim1).before(anim2); bouncer.play(anim2).with(anim3); bouncer.play(anim2).with(anim4) bouncer.play(anim5).after(amin2); animatorSet.start();
anim.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { //動畫開始時執行 } @Override public void onAnimationRepeat(Animator animation) { //動畫重復時執行 } @Override public void onAnimationEnd(Animator animation) { //動畫結束時執行 } @Override public void onAnimationCancel(Animator animation) { //動畫被取消時執行 } });Animator.AnimatorListener對象下,有4個未實現的方法,我們可以分別實現一下其中的方法,就可以方便的去監聽動畫執行整個過程了。但是Animator.AnimatorListener對象不夠簡潔,因為大部分時候我們只需要監聽動畫結束時的事件即可,那麼Android也為我們提供好了一個簡化的監聽對象AnimatorListenerAdapter,AnimatorListenerAdapter
anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { // TODO Auto-generated method stub super.onAnimationEnd(animation); } });
ValueAnimator包含Property Animation動畫的所有核心功能,如動畫時間,開始、結束屬性值,相應時間屬性值計算方法等。應用Property Animation有兩個步聚:
計算屬性值根據屬性值執行相應的動作,如改變對象的某一屬性。ValuAnimiator只完成了第一步工作,如果要完成第二步,需要實現ValueAnimator.onUpdateListener接口,這個接口只有一個函數onAnimationUpdate(),在這個函數中會傳入ValueAnimator對象做為參數,通過這個ValueAnimator對象的getAnimatedValue()函數可以得到當前的屬性值如:
protected void playAnim() { ValueAnimator animator = ValueAnimator.ofInt(0, 10); animator.setDuration(100); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Log.i(TAG, AnimatedValue : + animation.getAnimatedValue().toString()); } }); animator.start(); }
從上面的例子可以看到ValueAnimator類實現的是動畫的插值因子的計算,大部分情況下我們使用ObjectAnimator就可以輕松實現很多種動畫效果了,然後使用ObjectAnimator的View必須滿足有getter和setter方法,若沒有這些方法,使用ObjectAnimator的動畫是無法實現的,我們只好考慮使用ObjectAnimator的父類ValueAnimator了,ValueAnimator實現動畫不需要View含有getter和setter方法,它是通過計算動畫的插值因子,我們根據這個插值自定義動畫效果就可以了。
TypeEvaluator是一個接口,通過實現該接口下的evaluate方法,可以實現我們自定義的各種復雜效果的動畫:
ValueAnimator animator =ValueAnimator.ofObject(new TypeEvaluator上面就是實現的TypeEvaluator接口,下面有個未實現的方法,這個回調函數中提供如下三個參數:() { @Override public Number evaluate(float fraction, Number startValue,Number endValue) { // TODO Auto-generated method stub return null; } });
fraction:插值因子,取值范圍0~1 startValue:動畫的起始值 endValue:動畫的結束值 我們可以根據這3個參數來編寫計算自己需要的動畫效果,樣式很多樣化的,不僅僅是ObjectAnimator裡幾種動畫類型了。由此可以看出,ValueAnimator比ObjectAnimator更加靈活,方式更加繁多,我們自定義動畫效果時,可以使用ValueAnimator實現TypeEvaluator接口來寫自己的動畫算法,實現比較復雜的動畫。
在一些音樂類應用中, 經常會展示隨著節奏上下起伏的波紋信息, 這些波紋形象地傳達了聲音信息, 可以提升用戶體驗, 那麼是如何實現的呢? 可以使用Visualize
在開發Android應用時,保存數據有這麼幾個方式, 一個是本地保存,一個是放在後台(提供API接口),還有一個是放在開放雲服務上(如 SyncAdapter 會是一個不
1 背景其實這篇文章可能有些小題大作,但回過頭想想還是很有必要的,有點陰溝裡翻船的感覺。相信大家都知道Android API Level 8開始提供了為應用程序備份和恢復
在本篇博客中,我們分析一下Android中的APK是如何安裝的,以及PKMS在這個過程中進行了哪些工作。APK的安裝方式有很多,我們先來看看如何用adb命令進行安裝。我們