屬性動畫,快速打造,練手用
image.png
預覽圖:
menu.gif
一、制作圓形圖標
很方便地利用as自動生成圓形圖標:
- 右擊
res
,選擇Image Asset
:
image.png
- 選擇
Launcher Icons
,然后選Square
,其余自己調整:
image.png
現在,mipmap中有了相關圖片~~
當然,普通icon加個shape也是很方便的~
二、布局文件
很簡單,新建一個布局文件,記得把加號圖標放最下面,這樣就能遮住別的圖標,直接上代碼了:
//layout/circle_menu_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:orientation="vertical">
<ImageView
android:id="@+id/circle_menu_button_2"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="bottom|right"
android:layout_marginBottom="15dp"
android:layout_marginRight="15dp"
android:src="@mipmap/ic_edit1" />
<ImageView
android:id="@+id/circle_menu_button_3"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="bottom|right"
android:layout_marginBottom="15dp"
android:layout_marginRight="15dp"
android:src="@mipmap/ic_star" />
<ImageView
android:id="@+id/circle_menu_button_4"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="bottom|right"
android:layout_marginBottom="15dp"
android:layout_marginRight="15dp"
android:src="@mipmap/ic_cloud" />
<ImageView
android:id="@+id/circle_menu_button_5"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="bottom|right"
android:layout_marginBottom="15dp"
android:layout_marginRight="15dp"
android:src="@mipmap/ic_look" />
<ImageView
android:id="@+id/circle_menu_button_1"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="bottom|right"
android:layout_marginBottom="12dp"
android:layout_marginRight="12dp"
android:src="@mipmap/ic_add" />
</FrameLayout>
在總的布局文件中,直接include引入即可:
<include layout="@layout/circle_menu_layout" />
三、代碼中使用屬性動畫
- 首先定義變量,分別是資源id數組,圖片隊列,用來標明開關狀態的標志位
//扇形菜單按鈕
private int res[] ={R.id.circle_menu_button_1,R.id.circle_menu_button_2,R.id.circle_menu_button_3,R.id.circle_menu_button_4,R.id.circle_menu_button_5};
private ArrayList<ImageView> imageViews = new ArrayList<>();
//菜單是否展開的flag,false表示沒展開
private boolean mFlag = false;
- 利用for循環初始化圖標實例
for (int i = 0; i < res.length; i++) {
ImageView imageView = (ImageView) mContentView.findViewById(res[i]);
imageView.setOnClickListener(this);
imageViews.add(imageView);
}
- 在點擊事件
onClick()
中,判斷開關狀態后,開啟進入或者退出的動畫方法
case R.id.circle_menu_button_1:
if (mFlag == false){
showEnterAnim(100); //100為扇形半徑dp值
}else {
showExitAnim(100);
}
break;
- 下面來看看最重要的
showEnterAnim()
方法:
//顯示扇形菜單的屬性動畫
private void showEnterAnim(int dp) {
//for循環來開始小圖標的出現動畫
for (int i = 1; i < res.length; i++) {
AnimatorSet set = new AnimatorSet();
double x = -Math.cos(0.5/(res.length-2)*(i-1)*Math.PI)* Utils.dip2px(mContext,dp);
double y = -Math.sin(0.5/(res.length-2)*(i-1)*Math.PI)* Utils.dip2px(mContext,dp);
set.playTogether(
ObjectAnimator.ofFloat(imageViews.get(i),"translationX",(float)(x*0.25),(float)x),
ObjectAnimator.ofFloat(imageViews.get(i),"translationY",(float)(y*0.25),(float)y)
,ObjectAnimator.ofFloat(imageViews.get(i),"alpha",0,1).setDuration(2000)
);
set.setInterpolator(new BounceInterpolator());
set.setDuration(500).setStartDelay(100*i);
set.start();
}
//轉動加號大圖標本身45°
ObjectAnimator rotate = ObjectAnimator.ofFloat(imageViews.get(0),"rotation",0,45).setDuration(300);
rotate.setInterpolator(new BounceInterpolator());
rotate.start();
//菜單狀態置打開
mFlag = true;
}
唯一的難點就是根據第幾個小圖標,計算小圖標的xy軸坐標了,注意三角函數Math.sin()
的參數不是度數,而是弧度制的角度大小。
- 退出動畫其實和上面是相反的操作,參數前后換一下即可,但是考慮到是退出,所以應該時間短一點,變透明得快一點,且差值器就不用回彈效果了,可以用減速器的差值器(這樣一開始可以速度快點),代碼就不貼了。
- 上面用到了一個工具類函數
Utils.dip2px()
轉換dp參數為px值,如下:
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale);
}
四、總結
實現效果:
menu.gif
總的來說,屬性動畫可以快速方便地實現較為炫酷的效果,要自己多寫幾個經典的demo試試就行了。下一步可以學習更為厲害的VectorDrawable和貝塞爾曲線等等~~