属性动画,快速打造,练手用
预览图:
一、制作圆形图标
很方便地利用as自动生成圆形图标:
- 右击
res
,选择Image Asset
:
- 选择
Launcher Icons
,然后选Square
,其余自己调整:
现在,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);
}
四、总结
实现效果:
总的来说,属性动画可以快速方便地实现较为炫酷的效果,要自己多写几个经典的demo试试就行了。下一步可以学习更为厉害的VectorDrawable和贝塞尔曲线等等~~