編輯:關於Android編程
Android系統支持原生動畫,這為應用開發者開發絢麗的界面提供了極大的方便,有時候動畫是很必要的,當你想做一個滑動的特效的時候,如果苦思冥想都搞不定,那麼你可以考慮下動畫,說不定動畫輕易就搞定了。下面再簡單回顧下Android中的動畫,本文後面會介紹一個稍微復雜點的動畫,先上效果圖
View動畫:也叫漸變動畫,針對View的動畫,主要支持平移、旋轉、縮放、透明度
Drawable動畫:也叫幀動畫,主要是設置View的背景,可以以動畫的形式為View設置多張背景
對象屬性動畫(Android3.0新加入):可以對對象的屬性進行動畫而不僅僅是View,動畫默認時間間隔300ms,默認幀率10ms/幀。其可以達到的效果是:在一個時間間隔內完成對象從一個屬性值到另一個屬性值的改變,因此,屬性動畫幾乎是無所不能的,只要對象有這個屬性,它都能實現動畫效果,但是屬性動畫從Android3.0才有,這就嚴重制約了屬性動畫的使用,這就是開源動畫庫nineoldandroids的作用,采用nineoldandroids,可以在3.0以前的系統上使用屬性動畫,nineoldandroids的網址是:http://nineoldandroids.com。說到屬性動畫,就不得不提到插值器(TimeInterpolator)和估值算法(TypeEvaluator),下面介紹。
看上述動畫,很顯然上述動畫是一個勻速動畫,其采用了線性插值器和整型估值算法,在40ms內,View的x屬性實現從0到40的變換,由於動畫的默認刷新率為10ms/幀,所以該動畫將分5幀進行,我們來考慮第三幀(x=20 t=20ms),當時間t=20ms的時候,時間流逝的百分比是0.5 (20/40=0.5),意味這現在時間過了一半,那x應該改變多少呢,這個就由插值器和估值算法來確定。拿線性插值器來說,當時間流逝一半的時候,x的變換也應該是一半,即x的改變是0.5,為什麼呢?因為它是線性插值器,是實現勻速動畫的,下面看它的源碼:
publicclassLinearInterpolatorimplementsInterpolator{
publicLinearInterpolator(){
}
publicLinearInterpolator(Contextcontext,AttributeSetattrs){
}
publicfloatgetInterpolation(floatinput){
returninput;
}
}
很顯然,線性插值器的返回值和輸入值一樣,因此插值器返回的值是0.5,這意味著x的改變是0.5,這個時候插值器的工作就完成了。
具體x變成了什麼值,這個需要估值算法來確定,我們來看看整型估值算法的源碼:
publicclassIntEvaluatorimplementsTypeEvaluator{
publicIntegerevaluate(floatfraction,IntegerstartValue,IntegerendValue){
intstartInt=startValue;
return(int)(startInt+fraction*(endValue-startInt));
}
}
[java]view plaincopy
ObjectAnimator.ofFloat(myObject,"translationY",-myObject.getHeight()).start();
栗子2:改變一個對象的背景色屬性,典型的情形是改變View的背景色,下面的動畫可以讓背景色在3秒內實現從0xFFFF8080到0xFF8080FF的漸變,並且動畫會無限循環而且會有反轉的效果
[java]view plaincopy
ValueAnimatorcolorAnim=ObjectAnimator.ofInt(this,"backgroundColor",/*Red*/0xFFFF8080,/*Blue*/0xFF8080FF);
colorAnim.setDuration(3000);
colorAnim.setEvaluator(newArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.setRepeatMode(ValueAnimator.REVERSE);
colorAnim.start();
栗子3:動畫集合,5秒內對View的旋轉、平移、縮放和透明度都進行了改變
[java]view plaincopy
AnimatorSetset=newAnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(myView,"rotationX",0,360),
ObjectAnimator.ofFloat(myView,"rotationY",0,180),
ObjectAnimator.ofFloat(myView,"rotation",0,-90),
ObjectAnimator.ofFloat(myView,"translationX",0,90),
ObjectAnimator.ofFloat(myView,"translationY",0,90),
ObjectAnimator.ofFloat(myView,"scaleX",1,1.5f),
ObjectAnimator.ofFloat(myView,"scaleY",1,0.5f),
ObjectAnimator.ofFloat(myView,"alpha",1,0.25f,1)
);
set.setDuration(5*1000).start();
栗子4:下面是個簡單的調用方式,其animate方法是nineoldandroids特有的
[java]view plaincopy
ButtonmyButton=(Button)findViewById(R.id.myButton);
//Note:inordertousetheViewPropertyAnimatorlikethisaddthefollowingimport:
//importstaticcom.nineoldandroids.view.ViewPropertyAnimator.animate;
animate(myButton).setDuration(2000).rotationYBy(720).x(100).y(100);
栗子5:一個采用nineoldandroids實現的稍微復雜點的動畫
布局xml如下:
[html]view plaincopy
android:layout_height="match_parent">
android:id="@+id/menu"
style="@style/MenuStyle"
android:background="@drawable/menu"/>
android:id="@+id/item1"
style="@style/MenuItemStyle"
android:background="@drawable/circle1"
android:visibility="gone"/>
android:id="@+id/item2"
style="@style/MenuItemStyle"
android:background="@drawable/circle2"
android:visibility="gone"/>
android:id="@+id/item3"
style="@style/MenuItemStyle"
android:background="@drawable/circle3"
android:visibility="gone"/>
android:id="@+id/item4"
style="@style/MenuItemStyle"
android:background="@drawable/circle4"
android:visibility="gone"/>
android:id="@+id/item5"
style="@style/MenuItemStyle"
android:background="@drawable/circle5"
android:visibility="gone"/>
代碼如下:
[java]view plaincopy
publicclassMainActivityextendsActivityimplementsOnClickListener{
privatestaticfinalStringTAG="MainActivity";
privateButtonmMenuButton;
privateButtonmItemButton1;
privateButtonmItemButton2;
privateButtonmItemButton3;
privateButtonmItemButton4;
privateButtonmItemButton5;
privatebooleanmIsMenuOpen=false;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
privatevoidinitView(){
mMenuButton=(Button)findViewById(R.id.menu);
mMenuButton.setOnClickListener(this);
mItemButton1=(Button)findViewById(R.id.item1);
mItemButton1.setOnClickListener(this);
mItemButton2=(Button)findViewById(R.id.item2);
mItemButton2.setOnClickListener(this);
mItemButton3=(Button)findViewById(R.id.item3);
mItemButton3.setOnClickListener(this);
mItemButton4=(Button)findViewById(R.id.item4);
mItemButton4.setOnClickListener(this);
mItemButton5=(Button)findViewById(R.id.item5);
mItemButton5.setOnClickListener(this);
}
@Override
publicbooleanonCreateOptionsMenu(Menumenu){
mMenuButton.performClick();
getMenuInflater().inflate(R.menu.main,menu);
returnfalse;
}
@Override
publicvoidonClick(Viewv){
if(v==mMenuButton){
if(!mIsMenuOpen){
mIsMenuOpen=true;
doAnimateOpen(mItemButton1,0,5,300);
doAnimateOpen(mItemButton2,1,5,300);
doAnimateOpen(mItemButton3,2,5,300);
doAnimateOpen(mItemButton4,3,5,300);
doAnimateOpen(mItemButton5,4,5,300);
}else{
mIsMenuOpen=false;
doAnimateClose(mItemButton1,0,5,300);
doAnimateClose(mItemButton2,1,5,300);
doAnimateClose(mItemButton3,2,5,300);
doAnimateClose(mItemButton4,3,5,300);
doAnimateClose(mItemButton5,4,5,300);
}
}else{
Toast.makeText(this,"你點擊了"+v,Toast.LENGTH_SHORT).show();
}
}
/**
*打開菜單的動畫
*@paramview執行動畫的view
*@paramindexview在動畫序列中的順序
*@paramtotal動畫序列的個數
*@paramradius動畫半徑
*/
privatevoiddoAnimateOpen(Viewview,intindex,inttotal,intradius){
if(view.getVisibility()!=View.VISIBLE){
view.setVisibility(View.VISIBLE);
}
doubledegree=Math.PI*index/((total-1)*2);
inttranslationX=(int)(radius*Math.cos(degree));
inttranslationY=(int)(radius*Math.sin(degree));
Log.d(TAG,String.format("degree=%f,translationX=%d,translationY=%d",
degree,translationX,translationY));
AnimatorSetset=newAnimatorSet();
//包含平移、縮放和透明度動畫
set.playTogether(
ObjectAnimator.ofFloat(view,"translationX",0,translationX),
ObjectAnimator.ofFloat(view,"translationY",0,translationY),
ObjectAnimator.ofFloat(view,"scaleX",0f,1f),
ObjectAnimator.ofFloat(view,"scaleY",0f,1f),
ObjectAnimator.ofFloat(view,"alpha",0f,1));
//動畫周期為500ms
set.setDuration(1*500).start();
}
/**
*關閉菜單的動畫
*@paramview執行動畫的view
*@paramindexview在動畫序列中的順序
*@paramtotal動畫序列的個數
*@paramradius動畫半徑
*/
privatevoiddoAnimateClose(finalViewview,intindex,inttotal,
intradius){
if(view.getVisibility()!=View.VISIBLE){
view.setVisibility(View.VISIBLE);
}
doubledegree=Math.PI*index/((total-1)*2);
inttranslationX=(int)(radius*Math.cos(degree));
inttranslationY=(int)(radius*Math.sin(degree));
Log.d(TAG,String.format("degree=%f,translationX=%d,translationY=%d",
degree,translationX,translationY));
AnimatorSetset=newAnimatorSet();
//包含平移、縮放和透明度動畫
set.playTogether(
ObjectAnimator.ofFloat(view,"translationX",translationX,0),
ObjectAnimator.ofFloat(view,"translationY",translationY,0),
ObjectAnimator.ofFloat(view,"scaleX",1f,0f),
ObjectAnimator.ofFloat(view,"scaleY",1f,0f),
ObjectAnimator.ofFloat(view,"alpha",1f,0f));
//為動畫加上事件監聽,當動畫結束的時候,我們把當前view隱藏
set.addListener(newAnimatorListener(){
@Override
publicvoidonAnimationStart(Animatoranimator){
}
@Override
publicvoidonAnimationRepeat(Animatoranimator){
}
@Override
publicvoidonAnimationEnd(Animatoranimator){
view.setVisibility(View.GONE);
}
@Override
publicvoidonAnimationCancel(Animatoranimator){
}
});
set.setDuration(1*500).start();
}
}
一、簡介 1、地圖 地圖展示:普通地圖(2D,3D)、衛星圖和實時交通圖。 地圖操作:可通過接口或手勢控制來實現地圖的點擊、雙擊、長按、縮放
現在很多app的支付、輸入密碼功能,都已經開始使用自定義數字鍵盤,不僅更加方便、其效果著實精致。下面帶著大家學習下,如何高仿微信的數字鍵盤,可以拿來直接用在自身的項目中。
一.大致效果~別嫌它丑二.關鍵代碼在注釋中講重點吧。(1)Spinner的布局: car_brand_spinner.xml即為彈出來的下拉列表的布局啦,後面的那個布局就
一.前言現在的app基本上都需要用到短信功能,注冊時或者有消息通知時需要給用戶發送一條短信,但是對於個人開發者來說,去買第三方的短信服務實在是有點奢侈,很好的是mob為我