package com.loaderman.customviewdemo; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.Toast; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button mMenuButton; private Button mItemButton1; private Button mItemButton2; private Button mItemButton3; private Button mItemButton4; private Button mItemButton5; private boolean mIsMenuOpen = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { 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); } public void onClick(View v) { if (!mIsMenuOpen) { mIsMenuOpen = true; openMenu(); } else { Toast.makeText(this, "你点击了" + v, Toast.LENGTH_SHORT).show(); mIsMenuOpen = false; closeMenu(); } } private void openMenu() { 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); } private void closeMenu() { 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); } /** * 打开菜单的动画 * * @param view 执行动画的view * @param index view在动画序列中的顺序,从0开始 * @param total 动画序列的个数 * @param radius 动画半径 * <p/> * Math.sin(x):x -- 为number类型的弧度,角度乘以0.017(2π/360)可以转变为弧度 */ private void doAnimateOpen(View view, int index, int total, int radius) { if (view.getVisibility() != View.VISIBLE) { view.setVisibility(View.VISIBLE); } double degree = Math.toRadians(90) / (total - 1) * index; int translationX = -(int) (radius * Math.sin(degree)); int translationY = -(int) (radius * Math.cos(degree)); AnimatorSet set = new AnimatorSet(); //包含平移、缩放和透明度动画 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(500).start(); } /** * 关闭菜单的动画 * * @param view 执行动画的view * @param index view在动画序列中的顺序 * @param total 动画序列的个数 * @param radius 动画半径 */ private void doAnimateClose(final View view, int index, int total, int radius) { if (view.getVisibility() != View.VISIBLE) { view.setVisibility(View.VISIBLE); } double degree = Math.PI * index / ((total - 1) * 2); int translationX = -(int) (radius * Math.sin(degree)); int translationY = -(int) (radius * Math.cos(degree)); AnimatorSet set = new AnimatorSet(); //包含平移、缩放和透明度动画 set.playTogether( ObjectAnimator.ofFloat(view, "translationX", translationX, 0), ObjectAnimator.ofFloat(view, "translationY", translationY, 0), ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.1f), ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.1f), ObjectAnimator.ofFloat(view, "alpha", 1f, 0f)); /** * 解决方案二 */ // set.addListener(new Animator.AnimatorListener() { // public void onAnimationStart(Animator animation) { // // } // public void onAnimationEnd(Animator animation) { // view.setScaleX(1.0f); // view.setScaleY(1.0f); // // } // // public void onAnimationCancel(Animator animation) { // // } // public void onAnimationRepeat(Animator animation) { // // } // }); set.setDuration(500).start(); } }
<?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_marginBottom="10dp" android:layout_marginRight="10dp"> <Button android:id="@+id/menu" style="@style/MenuStyle" android:background="@drawable/menu"/> <Button android:id="@+id/item1" style="@style/MenuItemStyle" android:background="@drawable/circle1" android:visibility="gone"/> <Button android:id="@+id/item2" style="@style/MenuItemStyle" android:background="@drawable/circle2" android:visibility="gone"/> <Button android:id="@+id/item3" style="@style/MenuItemStyle" android:background="@drawable/circle3" android:visibility="gone"/> <Button android:id="@+id/item4" style="@style/MenuItemStyle" android:background="@drawable/circle4" android:visibility="gone"/> <Button android:id="@+id/item5" style="@style/MenuItemStyle" android:background="@drawable/circle5" android:visibility="gone"/> </FrameLayout>
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="MenuStyle"> <item name="android:layout_width">50dp</item> <item name="android:layout_height">50dp</item> <item name="android:layout_gravity">right|bottom</item> </style> <style name="MenuItemStyle"> <item name="android:layout_width">45dp</item> <item name="android:layout_height">45dp</item> <item name="android:layout_gravity">right|bottom</item> </style> </resources>
效果:
package com.loaderman.customviewdemo; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private Button mButton; private TextView mTv1, mTv2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mButton = (Button) findViewById(R.id.btn); mTv1 = (TextView) findViewById(R.id.tv_1); mTv2 = (TextView) findViewById(R.id.tv_2); mButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { /** * playSequentially 代表所有多动画依次播放 */ // ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(mTv1, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff); // ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 300, 0); // ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0); // // AnimatorSet animatorSet = new AnimatorSet(); // animatorSet.playSequentially(tv1BgAnimator, tv1TranslateY, tv2TranslateY); // animatorSet.setDuration(1000); // animatorSet.start(); /** * playTogether 代表所有动画一起播放 */ // ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(mTv1, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff); // ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 400, 0); // ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0); // // AnimatorSet animatorSet = new AnimatorSet(); // animatorSet.playTogether(tv1BgAnimator, tv1TranslateY, tv2TranslateY); // animatorSet.setDuration(1000); // animatorSet.start(); /** * 使用AnimatorSet.builder 可以自由组合动画,是playSequentially和playTogether的组合 */ ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(mTv1, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff); ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 400, 0); ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(tv1TranslateY).with(tv2TranslateY).after(tv1BgAnimator); animatorSet.setDuration(2000); animatorSet.start(); } }); } }
动画监听:
private AnimatorSet doListenerAnimation() { ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 400, 0); ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0); tv2TranslateY.setRepeatCount(ValueAnimator.INFINITE); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(tv1TranslateY).with(tv2TranslateY); animatorSet.addListener(new Animator.AnimatorListener() { public void onAnimationStart(Animator animation) { Log.d(tag, "animator start"); } public void onAnimationEnd(Animator animation) { Log.d(tag, "animator end"); } public void onAnimationCancel(Animator animation) { Log.d(tag, "animator cancel"); } public void onAnimationRepeat(Animator animation) { Log.d(tag, "animator repeat"); } }); animatorSet.setDuration(2000); animatorSet.start(); return animatorSet; }