ApiDemos 中的 ListFlipper
ListFlipper 是 ApiDemos 中的一個簡單的動畫特效示例,它直接繼承了 Activity,使用起來還是比較簡單的。他的作用是讓一個界面旋轉并且切換到另外一個界面上,是一個比較常見的切換動畫。
XML 布局
ApiDemos 中的 ListFlipper 只是一個簡單的示例,它的 XML 布局也非常簡單。就是一個線性布局, Button 用來控制觸發動畫效果,兩個 ListView ,其中一個 ListView 的 visibility 屬性為 gone.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Flip" />
<ListView
android:id="@+id/list_en"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1.0" />
<ListView
android:id="@+id/list_fr"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1.0"
android:visibility="gone" />
</LinearLayout>
ListFlipper 源碼
源碼原理很簡單,我在代碼里做了一些簡單的注釋。
public class ListFlipper extends Activity {
private static final String[] LIST_STRINGS_EN = new String[] { "One",
"Two", "Three", "Four", "Five", "Six" };
private static final String[] LIST_STRINGS_FR = new String[] { "Un",
"Deux", "Trois", "Quatre", "Le Five", "Six" };
ListView mEnglishList;
ListView mFrenchList;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// FrameLayout container = (LinearLayout) findViewById(R.id.container);
mEnglishList = (ListView) findViewById(R.id.list_en);
mFrenchList = (ListView) findViewById(R.id.list_fr);
// Prepare the ListView
final ArrayAdapter<String> adapterEn = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, LIST_STRINGS_EN);
// Prepare the ListView
final ArrayAdapter<String> adapterFr = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, LIST_STRINGS_FR);
mEnglishList.setAdapter(adapterEn);
mFrenchList.setAdapter(adapterFr);
// mFrenchList.setRotationY(-90f);
Button starter = (Button) findViewById(R.id.button);
starter.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
flipit();
}
});
}
private Interpolator accelerator = new AccelerateInterpolator();
private Interpolator decelerator = new DecelerateInterpolator();
private void flipit() {
// 定義兩個ListView,作用是充當容器
final ListView visibleList;
final ListView invisibleList;
// 如果英語List為不可見的
if (mEnglishList.getVisibility() == View.GONE) {
// 可見List存儲法語List
visibleList = mFrenchList;
// 不可見List存儲英語List
invisibleList = mEnglishList;
} else {// 相反
invisibleList = mFrenchList;
visibleList = mEnglishList;
}
// 繞Y軸0°到90°旋轉
ObjectAnimator visToInvis = ObjectAnimator.ofFloat(visibleList,
"rotationY", 0f, 90f);
visToInvis.setDuration(500);
// 在動畫開始的地方速率改變比較慢,然后開始加速
visToInvis.setInterpolator(accelerator);
// 不可見List繞Y軸逆時針旋轉90°
final ObjectAnimator invisToVis = ObjectAnimator.ofFloat(invisibleList,
"rotationY", -90f, 0f);
invisToVis.setDuration(500);
// 在動畫開始的地方快然后慢
invisToVis.setInterpolator(decelerator);
// 給可見List設置一個動畫監聽
visToInvis.addListener(new AnimatorListenerAdapter() {
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void onAnimationEnd(Animator anim) {
// 當動畫執行結束時,將可見List設置為不可見
visibleList.setVisibility(View.GONE);
// 啟動不可見List動畫
invisToVis.start();
// 將不可見List設置為可見的
invisibleList.setVisibility(View.VISIBLE);
}
});
// 啟動可見List的動畫
visToInvis.start();
}
}
Interpolator 調查
以前做動畫沒有接觸過 Interpolator,去調查了一下,說明如下。
Android:interpolator
Interpolator 被用來修飾動畫效果,定義動畫的變化率,可以使存在的動畫效果accelerated(加速),decelerated(減速),repeated(重復),bounced(彈跳)等。
android中的文檔內容如下:
AccelerateDecelerateInterpolator 在動畫開始與結束的地方速率改變比較慢,在中間的時候加速
AccelerateInterpolator 在動畫開始的地方速率改變比較慢,然后開始加速
AnticipateInterpolator 開始的時候向后然后向前甩
AnticipateOvershootInterpolator 開始的時候向后然后向前甩一定值后返回最后的值
BounceInterpolator 動畫結束的時候彈起
CycleInterpolator 動畫循環播放特定的次數,速率改變沿著正弦曲線
DecelerateInterpolator 在動畫開始的地方快然后慢
LinearInterpolator 以常量速率改變
OvershootInterpolator 向前甩一定值后再回到原來位置
如果android定義的interpolators不符合你的效果也可以自定義interpolators