一向以不重复造轮子为宗旨的小程序员,在找遍全网没找到称心的动画之后,只好自己写了个属性动画。也就产生了本人第一篇原创博客。OK,废话不多说,先上效果图。有点类似咸鱼的发布动画。
//MainActivity的布局xml代码:
"1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff988"
>
"@+id/boss1"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp"
android:background="@drawable/bg_oval_pink"
/>
//MainActivity的java代码
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
/**
* Created by staticman on 2016/12/28.
*/
public class MainActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.findViewById(R.id.boss1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), ActivityOpenAnim.class);
startActivity(intent);
}
});
}
}
//展开菜单的布局xml代码,每个ImageView的背景随便设置即可,这里就不贴上来了
"1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
"@+id/clickOut"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
"@+id/anim1"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp"
android:background="@drawable/bg_oval_blue"
/>
"@+id/anim2"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp"
android:background="@drawable/bg_oval_red"
/>
"@+id/anim3"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp"
android:background="@drawable/bg_oval_green"
/>
"@+id/boss"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp"
android:background="@drawable/bg_oval_pink"
/>
//ActivityOpenAnim的java代码
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.OvershootInterpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class ActivityOpenAnim extends AppCompatActivity {
boolean isOpen = false;
@BindView(R.id.anim1)
ImageView anim1;
@BindView(R.id.anim2)
ImageView anim2;
@BindView(R.id.anim3)
ImageView anim3;
@BindView(R.id.clickOut)
LinearLayout clickOut;
@BindView(R.id.boss)
ImageView boss;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_open_menu);
EventBus.getDefault().register(this);
ButterKnife.bind(this);
//进入页面等300ms之后再进行动画
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(300);//子线程中睡300ms是为了Acticity的布局初始化完毕才触发动画,否则动画会出现卡顿
boss.setClickable(false);//禁用点击,防止快速点击的时候动画未完成就再次开始
EventBus.getDefault().post(new OpenBean());//使用EventBus发送消息到主线程的订阅事件开启动画,使用handler也可以
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
//所有的点击事件
@OnClick({R.id.clickOut, R.id.boss, R.id.anim1, R.id.anim2, R.id.anim3})
public void onClick(View view) {
switch (view.getId()) {
case R.id.clickOut://点击任意空白处均可关闭此页面
case R.id.boss:
if (isOpen) {
isOpen = !isOpen;
animRunBack(anim1, anim2, anim3);//关闭时开启收回动画
}
break;
case R.id.anim1:
finish();
break;
case R.id.anim2:
finish();
break;
case R.id.anim3:
finish();
break;
}
}
//eventbus的订阅事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(OpenBean openBean) {
if (!isOpen) {
isOpen = !isOpen;//禁止快速点击
animRun(anim1, anim2, anim3);
}
}
//菜单展开的动画
public void animRun(final View view1, final View view2, final View view3) {
//获取屏幕宽度
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
final int screenWidth = dm.widthPixels;
//左边控件的动画
ObjectAnimator animator1 = ObjectAnimator.ofFloat(view1, "translationY",
0.0F, -screenWidth / 3f).setDuration(300);//Y方向移动距离
ObjectAnimator animator2 = ObjectAnimator.ofFloat(view1, "translationX",
0.0F, -screenWidth / 4f).setDuration(300);//X方向移动距离
ObjectAnimator animator3 = ObjectAnimator.ofFloat(view1, "scaleX", 1.0f, 1.5f).setDuration(300);//X方向放大
ObjectAnimator animator4 = ObjectAnimator.ofFloat(view1, "scaleY", 1.0f, 1.5f).setDuration(300);//Y方向放大
AnimatorSet animSet1 = new AnimatorSet();
animSet1.setInterpolator(new OvershootInterpolator());//到达指定位置后继续向前移动一定的距离然后弹回指定位置,达到颤动的特效
animSet1.playTogether(animator1, animator2, animator3, animator4);//四个动画同时执行
//中间控件的动画,因需要设置监听所以与
final ObjectAnimator animator5 = ObjectAnimator.ofFloat(view2, "translationY",
0.0F, -screenWidth / 2f).setDuration(300);
ObjectAnimator animator6 = ObjectAnimator.ofFloat(view2, "scaleX", 1.0f, 1.5f).setDuration(300);
ObjectAnimator animator7 = ObjectAnimator.ofFloat(view2, "scaleY", 1.0f, 1.5f).setDuration(300);
final AnimatorSet animatorSet2 = new AnimatorSet();
animatorSet2.setInterpolator(new OvershootInterpolator());
animatorSet2.playTogether(animator5, animator6, animator7);
animatorSet2.setStartDelay(50);//监听第一个动画开始之后50ms开启第二个动画,达到相继弹出的效果
//右侧控件的动画
ObjectAnimator animator8 = ObjectAnimator.ofFloat(view3, "translationY",
0.0F, -screenWidth / 3).setDuration(300);
ObjectAnimator animator9 = ObjectAnimator.ofFloat(view3, "translationX",
0.0F, screenWidth / 4f).setDuration(300);
ObjectAnimator animator10 = ObjectAnimator.ofFloat(view3, "scaleX", 1.0f, 1.5f).setDuration(300);
ObjectAnimator animator11 = ObjectAnimator.ofFloat(view3, "scaleY", 1.0f, 1.5f).setDuration(300);
final AnimatorSet animatorSet3 = new AnimatorSet();
animatorSet3.setInterpolator(new OvershootInterpolator());
animatorSet3.playTogether(animator8, animator9, animator10, animator11);
animatorSet3.setStartDelay(50);
//三个动画结束之后设置boss按键可点击,点击即收回动画
animatorSet3.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
boss.setClickable(true);
}
});
//第二个开始之后再开启第三个
animator3.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
animatorSet3.start();
}
});
//第一个动画开始之后再开启第二个
animSet1.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
animatorSet2.start();
}
});
animSet1.start();//放在最后是为了初始化完毕所有的动画之后才触发第一个控件的动画
}
//收回动画,相当于反向执行展开动画,此处不做更详细的注释
public void animRunBack(final View view1, final View view2, final View view3) {
//获取屏幕宽度
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
final int screenWidth = dm.widthPixels;
//第一个收回动画
ObjectAnimator animator1 = ObjectAnimator.ofFloat(view1, "translationY",
-screenWidth / 3f, 0.0F).setDuration(300);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(view1, "translationX",
-screenWidth / 4f, 0.0F).setDuration(300);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(view1, "scaleX", 1.5f, 1.0f).setDuration(300);
ObjectAnimator animator4 = ObjectAnimator.ofFloat(view1, "scaleY", 1.5f, 1.0f).setDuration(300);
AnimatorSet animSet = new AnimatorSet();
animSet.setInterpolator(new DecelerateInterpolator());
animSet.playTogether(animator1, animator2, animator3, animator4);
//第二个收回动画
final ObjectAnimator animator5 = ObjectAnimator.ofFloat(view2, "translationY",
-screenWidth / 2f, 0.0F).setDuration(300);
ObjectAnimator animator6 = ObjectAnimator.ofFloat(view2, "scaleX", 1.5f, 1.0f).setDuration(300);
ObjectAnimator animator7 = ObjectAnimator.ofFloat(view2, "scaleY", 1.5f, 1.0f).setDuration(300);
// animator3.setInterpolator(new OvershootInterpolator());
final AnimatorSet animatorSet2 = new AnimatorSet();
animatorSet2.setInterpolator(new DecelerateInterpolator());
animatorSet2.playTogether(animator5, animator6, animator7);
animatorSet2.setStartDelay(50);
//第三个收回动画
ObjectAnimator animator8 = ObjectAnimator.ofFloat(view3, "translationY",
-screenWidth / 3, 0.0F).setDuration(300);
ObjectAnimator animator9 = ObjectAnimator.ofFloat(view3, "translationX",
screenWidth / 4f, 0.0F).setDuration(300);
ObjectAnimator animator10 = ObjectAnimator.ofFloat(view3, "scaleX", 1.5f, 1.0f).setDuration(300);
ObjectAnimator animator11 = ObjectAnimator.ofFloat(view3, "scaleY", 1.5f, 1.0f).setDuration(300);
final AnimatorSet animatorSet3 = new AnimatorSet();
animatorSet3.setInterpolator(new DecelerateInterpolator());
//四个动画同时执行
animatorSet3.playTogether(animator8, animator9, animator10, animator11);
animatorSet3.setStartDelay(50);
animator3.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
animatorSet3.start();
animatorSet3.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
finish();//收回动画结束后finish此页面
}
});
}
});
animSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
animatorSet2.start();
}
});
animSet.start();
}
//优化返回键的点击事件
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && isOpen) {
isOpen = !isOpen;
boss.setClickable(false);
animRunBack(anim1, anim2, anim3);
}
return false;
}
//必须在ondestroy中注销eventbus,否则会出事件重复执行的bug.
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
//其中空类OpenBean
package com.it.animdemo;
/**
* Created by staticman on 2016/12/28.
*/
public class OpenBean {
public OpenBean() {
}
}
//菜单页的主题
<resources>
<style name="HalfTrans" parent="AppTheme">
<item name="android:windowIsTranslucent">trueitem>
<item name="android:windowBackground">@color/halfTrans
style>
resources>
//其中半透明的背景色是
<color name="halfTrans">#80000000color>
//在清单文件中配置如下配置
<activity android:name=".ActivityOpenAnim"
android:theme="@style/HalfTrans"
/>
OK,睡觉.