属性动画-菜单以散开的方式弹出
我们先来看XML文件,文件名是activity_main.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <ImageView android:id="@+id/img_b" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="20dp" android:src="@mipmap/ic_launcher"/> <ImageView android:id="@+id/img_c" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="20dp" android:src="@mipmap/ic_launcher"/> <ImageView android:id="@+id/img_d" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="20dp" android:src="@mipmap/ic_launcher"/> <ImageView android:id="@+id/img_e" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="20dp" android:src="@mipmap/ic_launcher"/> <ImageView android:id="@+id/img_a" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:src="@mipmap/ic_launcher"/> </FrameLayout>
很简单,一个framlayout布局,然后,将所有的子按钮和菜单按钮叠放在一起。需要注意的是,要将最后显示的图片(也就是所谓的菜单按钮)放在最上面。
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ //数组存放图片ID,通过list进行图片遍历 private int[] res = {R.id.img_a,R.id.img_b, R.id.img_c,R.id.img_d,R.id.img_e}; private List<ImageView> list_img = new ArrayList<ImageView>(); /* 1. flag为true,当点击按钮的时候,弹出菜单 2. flag为false,当点击按钮的时候,收回菜单 */ private boolean flag = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); for(int i=0;i<res.length;i++){ ImageView img = (ImageView) findViewById(res[i]); img.setOnClickListener(this); list_img.add(img); } } @Override public void onClick(View view){ switch (view.getId()){ case R.id.img_a: if(flag){ startAnim(); //弹出菜单动画 }else{ closeAnim(); //收回菜单动画 } break; default: //这里只是简单的对弹出按钮的点击响应进行了处理,具体应用时可以进行完善 Toast.makeText(MainActivity.this,"click"+view.getId(), Toast.LENGTH_SHORT).show(); break; } } private void closeAnim(){ for(int i =1;i<res.length;i++){ //给出一个沿Y轴移动的动画 ObjectAnimator animator = ObjectAnimator.ofFloat( list_img.get(i),"translationY",(res.length-i-1)*50f,0f ); //给出一个沿X轴移动的动画 ObjectAnimator animator1 = ObjectAnimator.ofFloat( list_img.get(i),"translationX",(i-1)*50f,0f ); //定义属性动画集合的对象 AnimatorSet animSet = new AnimatorSet(); //通过with方法,让两个动画同时进行 animSet.play(animator).with(animator1); //设置延迟时间,让菜单内容相继弹出 animSet.setStartDelay(500); animSet.start(); //然后,设置flag为true,当再次点击的时候,收回菜单 flag = true; } } //两种方法的内容大体相同,只是动画属性的参数相反 private void startAnim() { for(int i =1;i<res.length;i++){ ObjectAnimator animator = ObjectAnimator.ofFloat( list_img.get(i),"translationY", 0f,(res.length-i-1)*50f ); ObjectAnimator animator1 = ObjectAnimator.ofFloat( list_img.get(i),"translationX", 0f , (i-1)*50f ); AnimatorSet animSet = new AnimatorSet(); animSet.play(animator).with(animator1); animSet.setStartDelay(500); animSet.start(); flag = false; } } }
对照上面的代码,进行下面的一些解释:
1、这里解释一下ObjectAnimator对象的参数的含义:
ObjectAnimator animator = ObjectAnimator.ofFloat(
list_img.get(i),”translationY”,
0f,(res.length-i-1)*50f );
第一个是object对象,添加的是我们所要赋予动画效果的对象,
如我们的list_img.get(i)
第二个是动画属性,也就是我们想要的动画效果
之后的就是设置动画属性的参数,跟animation动画参数设置一样。
2、下面说明一下动画属性的参数设置:
再来明确一下我们的目的:我们的目的,是想让菜单里的子按钮依次散布在菜单按钮的周围,形成直角。因此,各个子按钮的Y值应该是依次减小的,而它们的X值则是依次增加,并且这个动画变化过程是同时进行的。 好,下面,我们借助list来进行参数设置。
对于”translationY”,我们让它从Y=0 的地方,依次往外弹出(res.length-i-1)*50f 的距离。50F是我们设置的各个子按钮之间Y轴的距离。i则代表我们加载的图片资源的序号。这里要注意!我们的i是从1开始的。也就是让菜单按钮保持不动,所以,为了让最后一个子按钮的Y值为零,也就是跟屏幕上端平行,我们还要再减一,即我们的乘数因子为(res.length-i-1)。当i=1的时候,第一个子按钮的Y值最大,距离屏幕上端最远,然后,随着i值的增大,子按钮的Y值逐渐减小,距离屏幕上端也越来越近。
同理,对于”translationX”,则是从X=0的地方,依次弹出(i-1)*50f的距离。
2、closeAnim()方法内容跟startAnim()大体相同,只是参数设置上略有区别。收回菜单的是,子按钮的动画轨迹跟弹出的时候是相反的,所以,我们只需要把动画属性的参数调换一下位置即可。如有疑问,请参考代码进行对比。