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;
}

AnimatorSet学习示例代码的更多相关文章

  1. 一、从GitHub浏览Prism示例代码的方式入门WPF下的Prism

    最近这段时间一直在看一个开源软件PowerToys的源码,里面使用Modules的开发风格让我特别着迷,感觉比我现在写代码的风格好了太多太多.我尝试把PowerToys的架构分离了出来,但是发现代码维 ...

  2. 正则表达式学习笔记(附:Java版示例代码)

    具体学习推荐:正则表达式30分钟入门教程 .         除换行符以外的任意字符\w      word,正常字符,可以当做变量名的,字母.数字.下划线.汉字\s        space,空白符 ...

  3. Spring 注解学习 详细代码示例

    学习Sping注解,编写示例,最终整理成文章.如有错误,请指出. 该文章主要是针对新手的简单使用示例,讲述如何使用该注释,没有过多的原理解析. 已整理的注解请看右侧目录.写的示例代码也会在结尾附出. ...

  4. PyQt(Python+Qt)学习随笔:工具箱(QToolBox)编程使用的步骤及示例代码

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 使用toolBox开发应用时,通过Designer设计ui界面时,只能在Designer中设计too ...

  5. 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题

    调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...

  6. redis 学习笔记(2)-client端示例代码

    redis提供了几乎所有主流语言的client,java中主要使用二种:Jedis与Redisson 一.Jedis的使用 <dependency> <groupId>redi ...

  7. 【译】用Fragment创建动态的界面布局(附Android示例代码)

    原文链接:Building a Dynamic UI with Fragments 为了在Android上创建一个动态和多视图的用户界面,你需要封装UI控件和模块化Activity的行为,以便于你能够 ...

  8. C# 6新特性及示例代码

    今天推荐的其实是一个Github开源项目,不过这个开源项目是专门介绍C# 6的最新特性,并给出了示例代码. 我们知道,微软即将发布Windows 10和Visual Studio 2015,在VS20 ...

  9. Swift常用语法示例代码(二)

    此篇文章整理自我以前学习Swift时的一些练习代码,其存在的意义多是可以通过看示例代码更快地回忆Swift的主要语法. 如果你想系统学习Swift或者是Swift的初学者请绕路,感谢Github上Th ...

随机推荐

  1. python高级特性-filter

    python内建的函数filter用于过滤序列 和map()相同:filter()也接收一个函数的序列. 和map()不同:filter()把传入的函数依次依次作用于每个元素,然后根据返回值是True ...

  2. zstu月赛 招生

    题目 浙江理工大学招生,一开始有0名学生报考,现在有如下几种情况: 1.增加一名报考学生,报考学生成绩为x: 2.一名成绩为x的学生放弃报考. 3.从现在报考的学生来看,老师想知道如果要招生至少x名学 ...

  3. linux网络编程之socket编程(十六)

    继续学习socket编程,今天的内容会有些难以理解,一步步来分解,也就不难了,正入正题: 实际上sockpair有点像之前linux系统编程中学习的pipe匿名管道,匿名管道它是半双工的,只能用于亲缘 ...

  4. UML之九种图

    UML说是九种图吧!其实是众说纷纭,不管有几种图,我们只要能够很好的运用这几张图就好,主要有用例图.类图.对象图.状态图.活动图.序列图.协作图.构件图和部署图,至于包图是否属于这九种图,我也理不清楚 ...

  5. DT6.0二次最后一次开发插件-手机端熊掌号定时提交

    今天写完这个,就是DT6.0最后开放的插件,因为群里的朋友需要,就写了一个适合DT6的手机端定时插件.不过个人还是喜欢7.0的版本,7.0的插件在上几期分享了,今天就不过多说了! 我这个是初成品,改善 ...

  6. Linux运行shell脚本提示No such file or directory错误的解决办法

    Linux执行.sh文件,提示No such file or directory的问题: 原因:在windows中写好shell脚本测试正常,但是上传到 Linux 上以脚本方式运行命令时提示No s ...

  7. Http 请求头 响应体 详解

    Referrer Policy 是什么? 我们知道,在页面引入图片.JS 等资源,或者从一个页面跳到另一个页面,都会产生新的 HTTP 请求, 浏览器一般都会给这些请求头加上表示来源的 Referre ...

  8. JavaSctipt 常用字符串 方法及使用方式

    1. charAt(x) charAt(x)返回字符串中x位置的字符,下标从 0 开始. //charAt(x) var myString = 'jQuery FTW!!!'; console.log ...

  9. CF369E Valera and Queries kdtree

    给你一堆线段,求:一个区间内包含的本质不同线段种类数(只要线段有一部分在区间中就算是包含) 考虑容斥:总线段数-被那些没有询问的区间完全覆盖的数量. 用离线+树状数组数点或者 KDtree 数点即可. ...

  10. 对深层嵌套对象进行取值&赋值

    需求如下: let obj = { foo: { bar: { name: 'biz' } } }; // 输出 'biz' this.getObj(obj, 'foo.bar.name'); obj ...