編輯:關於Android編程
Android開發過程中,適當的使用一些動畫可以讓自己的應用看起來更棒更炫。最初的時候Google為了實現動畫,主要提供了兩種基本動畫:
幀動畫:將一個完整的動畫拆分成一張張單獨的圖片,然後再將它們連貫起來進行播放
補間動畫:無需逐一定義每一幀,只要定義開始、結束的幀,和指定動畫持續時間。
到了Android3.0,Google推出了一種新的動畫模式,屬性動畫。屬性動畫是對補間動畫的進一步完善和強化。
關於這個問題,可以借鑒一下郭霖的一段話:
補間動畫機制其實還算是比較健全的,可以讓我們實現View的移動、縮放、旋轉和淡入淡出效果,並且我們還可以借助AnimationSet來將這些動畫效果組合起來使用,除此之外還可以通過配置Interpolator來控制動畫的播放速度等等等等。那麼這裡大家可能要產生疑問了,既然之前的動畫機制已經這麼健全了,為什麼還要引入屬性動畫呢?
其實上面所謂的健全都是相對的,如果你的需求中只需要對View進行移動、縮放、旋轉和淡入淡出操作,那麼補間動畫確實已經足夠健全了。但是很顯然,這些功能是不足以覆蓋所有的場景的,一旦我們的需求超出了移動、縮放、旋轉和淡入淡出這四種對View的操作,那麼補間動畫就不能再幫我們忙了,也就是說它在功能和可擴展方面都有相當大的局限性,那麼下面我們就來看看補間動畫所不能勝任的場景。
注意上面我在介紹補間動畫的時候都有使用“對View進行操作”這樣的描述,沒錯,補間動畫是只能夠作用在View上的。也就是說,我們可以對一個Button、TextView、甚至是LinearLayout、或者其它任何繼承自View的組件進行動畫操作,但是如果我們想要對一個非View的對象進行動畫操作,抱歉,補間動畫就幫不上忙了。可能有的朋友會感到不能理解,我怎麼會需要對一個非View的對象進行動畫操作呢?這裡我舉一個簡單的例子,比如說我們有一個自定義的View,在這個View當中有一個Point對象用於管理坐標,然後在onDraw()方法當中就是根據這個Point對象的坐標值來進行繪制的。也就是說,如果我們可以對Point對象進行動畫操作,那麼整個自定義View的動畫效果就有了。顯然,補間動畫是不具備這個功能的,這是它的第一個缺陷。
然後補間動畫還有一個缺陷,就是它只能夠實現移動、縮放、旋轉和淡入淡出這四種動畫操作,那如果我們希望可以對View的背景色進行動態地改變呢?很遺憾,我們只能靠自己去實現了。說白了,之前的補間動畫機制就是使用硬編碼的方式來完成的,功能限定死就是這些,基本上沒有任何擴展性可言。
最後,補間動畫還有一個致命的缺陷,就是它只是改變了View的顯示效果而已,而不會真正去改變View的屬性。什麼意思呢?比如說,現在屏幕的左上角有一個按鈕,然後我們通過補間動畫將它移動到了屏幕的右下角,現在你可以去嘗試點擊一下這個按鈕,點擊事件是絕對不會觸發的,因為實際上這個按鈕還是停留在屏幕的左上角,只不過補間動畫將這個按鈕繪制到了屏幕的右下角而已。正是因為這些原因,功能更為完善和強大的屬性動畫就應運而生了。
從圖中可以看出,補間動畫主要是使用android.view.animation.Animation包下面的五個類來實現不同的動畫效果;而屬性動畫主要是使用android.animation.Animator的ValueAnimator以及其子類ObjectAnimator來實現不同的動畫效果。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxzdHJvbmc+VmFsdWVBbmltYXRvcjwvc3Ryb25nPg0KPHA+tNPK9NDUtq+7rc/gudi21M/ztcS8zLPQudjPtb/J0tS/tLP2o6xWYWx1ZUFuaW1hdG9yysexyL3PusvQxLXE0ru49sDgoaO52be9zsS1tbXEvenJ3MrHo7p0aGlzIGNsYXNzIHByb3ZpZGVzIGEgc2ltcGxlIHRpbWluZyBlbmdpbmUgZm9yIHJ1bm5pbmcgYW5pbWF0aW9ucyB3aGljaCBjYWxjdWxhdGUgYW5pbWF0ZWQgdmFsdWVzIGFuZCBzZXQgdGhlbSBvbiB0YXJnZXQgb2JqZWN0cyZoZWxsaXA70rK+zcrHy7VWYWx1ZUFuaW1hdG9yttTP88Tasr/OrLPWwcvSu7j2vPK1pbXEyrG85NL9x+ajrLzGy+PUy9DQtq+7rbXEvt/M5da1zazKsbDRy/zDx8no1sO4+MS/seq21M/zoaPNqMvXtcS9sr7NysejrFZhbHVlQW5pbWF0b3K1xMTasr/KudPD0rvW1sqxvOTRrbu3tcS7+tbGwLS8xsvj1rXT69a11q685LXEtq+7rbn9tsmjrM7Sw8fWu9Do0qq9q7P1yrzWtbrNveHK+Na1u/LV39bQvOTWtczhuam4+FZhbHVlQW5pbWF0b3KjrLKix9LJ6NbDtq+7rdTL0NDKsbOko6zEx8O0VmFsdWVBbmltYXRvcr7Nu+HX1LavzeqzybTTs/XKvNa1xr27rLn9tsm1vb3hyvjWtdXi0fm1xNCnufuho7b4x9KjrFZhbHVlQW5pbWF0b3K7ubi61PC53MDttq+7rbXEsqW3xbTOyv2horKlt8XEo8q9oaLS1LywttS2r7utyejWw7zgzP3G97XIoaPLtbXEt8+7sLHIvc+24KOsz8i+2bj2wPXX06Osx9DJ7czlu+HSu8/Co6E8L3A+DQo8cD48c3Ryb25nPjEu0Ke5+828PC9zdHJvbmc+PC9wPg0KPHA+PGltZyBhbHQ9"ValueAnimator" src="/uploadfile/Collfiles/20160912/20160912092704460.gif" title="\" />
2.具體代碼
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f); valueAnimator.setDuration(3000); //設置監聽,把當前AnimatedValue的值時時顯示到EditText上面 valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float currentValue = (float) animation.getAnimatedValue(); StringBuilder sb = new StringBuilder(); et_Animator.setText(sb.append(currentValue).toString()); } }); valueAnimator.start();
ValueAnimator比較常用的方法有:設置AnimatorValue區間范圍的三個主要方法
ofFloat(),ofInt(),ofObject()
還有設置延時播放時間的setStartDelay()方法,設置重復次數的setRepeatCount()方法,設置重復模式的setRepeatMode()
暫停動畫的pause()方法,恢復動畫的resume()等等,還有很多方法,具體大家可以查閱文檔,把這個核心類的方法掌握了,使用ObjectAnimator就能更加得心應手,因為從繼承關系中我們可以知道ObjectAnimator是ValueAnimator的子類。
ObjectAnimator對象應該是我們產生屬性動畫效果最常用的類了,ValueAnimator僅僅是對數值進行平滑的過渡變化,而如果我們想對一個對象的任意屬性進行動畫效果,就需要使用ObjectAnimator對象了,還是先舉個簡單栗子吧。
1.效果圖
2.具體代碼
//ofFloat(需要實現動畫的控件ID,需要實現的動畫效果名稱,變化的區間范圍) ObjectAnimator objAnim = bjectAnimator.ofFloat(et_Animator,"alpha",0f, 1f, 0f, 1f); objAnim.setDuration(6000); objAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float currentValue = (float) animation.getAnimatedValue(); StringBuilder sb = new StringBuilder(); et_Animator.setText(sb.append(currentValue).toString()); } }); objAnim.start();
以上代碼實現的效果是:在6000毫秒內,讓EditText控件平滑的實現了從完全透明>完全不透明>完全透明>完全不透明的過渡效果;並且對整個動畫執行過程設置了監聽,時時把當前動畫的AnimatorValue值顯示到EditText控件上面。
根據設置參數的不同,使用ObjectAnimator對象還可以實現translationX(豎直平移),translationY(水平平移),rotation(旋轉),scaleX(水平縮放),scaleY(豎直縮放)等其他效果。當然還可以使用AnimatorSet對象來產生組合動畫效果。
效果圖 具體代碼public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button btn_OperationAnimator; private EditText et_Animator; private RadioGroup radioGroup; private ObjectAnimator objAnim; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_Animator = (EditText) findViewById(R.id.et_Animator); radioGroup = (RadioGroup) findViewById(R.id.radioGroup); btn_OperationAnimator = (Button) findViewById(R.id.btn_OperationAnimator); btn_OperationAnimator.setOnClickListener(this); } @Override public void onClick(View v) { int checkedId = radioGroup.getCheckedRadioButtonId(); switch (checkedId) { case R.id.rb_value: ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f); valueAnimator.setDuration(3000); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float currentValue = (float) animation.getAnimatedValue(); StringBuilder sb = new StringBuilder(); et_Animator.setText(sb.append(currentValue).toString()); } }); valueAnimator.start(); break; case R.id.rb_alpha: objAnim = ObjectAnimator.ofFloat(et_Animator,"alpha",0f, 1f, 0f, 1f); objAnim.setDuration(3000); objAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float currentValue = (float) animation.getAnimatedValue(); StringBuilder sb = new StringBuilder(); et_Animator.setText(sb.append(currentValue).toString()); } }); objAnim.start(); break; case R.id.rb_translationX: objAnim = ObjectAnimator.ofFloat(et_Animator,"translationX",0f, 100f, 0f, 200f, 0f); objAnim.setDuration(3000); objAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float currentValue = (float) animation.getAnimatedValue(); StringBuilder sb = new StringBuilder(); et_Animator.setText(sb.append(currentValue).toString()); } }); objAnim.start(); break; case R.id.rb_translationY: objAnim = ObjectAnimator.ofFloat(et_Animator,"translationY",0f, 100f, 0f, 200f, 0f); objAnim.setDuration(3000); objAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float currentValue = (float) animation.getAnimatedValue(); StringBuilder sb = new StringBuilder(); et_Animator.setText(sb.append(currentValue).toString()); } }); objAnim.start(); break; case R.id.rb_rotation: objAnim = ObjectAnimator.ofFloat(et_Animator,"rotation",0f, 180f, 0f, 360f, 0f); objAnim.setDuration(6000); objAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float currentValue = (float) animation.getAnimatedValue(); StringBuilder sb = new StringBuilder(); et_Animator.setText(sb.append(currentValue).toString()); } }); objAnim.start(); break; case R.id.rb_scaleX: objAnim = ObjectAnimator.ofFloat(et_Animator,"scaleX", 4f, 1f, 2f, 1f); objAnim.setDuration(3000); objAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float currentValue = (float) animation.getAnimatedValue(); StringBuilder sb = new StringBuilder(); et_Animator.setText(sb.append(currentValue).toString()); } }); objAnim.start(); break; case R.id.rb_scaleY: objAnim = ObjectAnimator.ofFloat(et_Animator,"scaleY",1f, 5f, 2f, 1f); objAnim.setDuration(3000); objAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float currentValue = (float) animation.getAnimatedValue(); StringBuilder sb = new StringBuilder(); et_Animator.setText(sb.append(currentValue).toString()); } }); objAnim.start(); break; case R.id.rb_animatorSet: ObjectAnimator objAnim_alpha = ObjectAnimator.ofFloat(et_Animator,"alpha",0f, 1f, 0f, 1f); ObjectAnimator objAnim_translationX = ObjectAnimator.ofFloat(et_Animator,"translationX",0f, 100f, 0f, 200f, 0f); ObjectAnimator objAnim_translationY = ObjectAnimator.ofFloat(et_Animator,"translationY",0f, 100f, 0f, 200f, 0f); ObjectAnimator objAnim_rotation = ObjectAnimator.ofFloat(et_Animator,"rotation",0f, 180f, 0f, 360f, 0f); ObjectAnimator objAnim_scaleX = ObjectAnimator.ofFloat(et_Animator,"scaleX", 4f, 1f, 2f, 1f); ObjectAnimator objAnim_scaleY = ObjectAnimator.ofFloat(et_Animator,"scaleY",1f, 5f, 2f, 1f); AnimatorSet animSet = new AnimatorSet(); animSet.play(objAnim_alpha) .before(objAnim_rotation) //在play動畫之後執行 .after(objAnim_scaleX) //在play動畫之前執行 .after(objAnim_scaleY) .with(objAnim_translationX) //和play動畫同時執行 .with(objAnim_translationY); animSet.setDuration(5000); animSet.start(); break; } } }
栗子很簡單,算是做個自我鞏固以及方便日後回顧,如果不小心幫到別人了那自然也是極好的。
Android studio 百度地圖開發(3)地圖導航email:[email protected]開發環境:win7 64位,Android Studio,
觀察者模式(Observer)觀察者模式是對象的行為模式,又被叫做為模型-視圖模式。這種模式定義了一種一對多的依賴關系,使多個觀察者對象同時監聽某個角色對象。一旦這個角色
Android多終端適配是我們在實際開發中必然會遇到也必然要解決的問題,解決多終端適配的方法有很多,比如使用百分比布局庫(percent-support-lib)、在re
Intent 的 ComponentName 廣播-BroadcastReceiver ContentProvider AIDLIntent 的 ComponentNam