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. Django session默认配置

    配置 settings.py     SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)           SESSI ...

  2. Bash基础——内置命令

    前言 Shell有很多内置在其源代码中的命令.由于命令是内置的,所以Shell不必到磁盘上搜索它们.内置命令执行速度更快,不同的Shell内置命令有所不同. 如何查找内置命令 之前查了好久怎么收索内置 ...

  3. 用js刷剑指offer(从上到下打印二叉树)

    题目描述 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 牛客网链接 js代码 /* function TreeNode(x) { this.val = x; this.left = null ...

  4. Go语言使用Godep进行包管理

    一.为什么要包管理 默认Go的第三方包都是放在Gopath的src目录下,而且这些包都没有版本号的概念,这样的可能会出现一些问题. 举个例子:当A同事将开发完程序之后,此时可能引用了一个第三方的包,过 ...

  5. NodeJS开发博客(二) 接入数据库

    1. mysql 数据库下载网址:https://dev.mysql.com/downloads/mysql/ 账号是 root 密码是 a1************ 网站账号是邮箱,密码是 Aa1* ...

  6. Hive窗口函数案例详解

    语法: 分析函数 over(partition by 列名 order by 列名 rows between 开始位置 and 结束位置) 常用分析函数: 聚合类 avg().sum().max(). ...

  7. MySQL5.7版本安装(压缩包形式)

    1.去官网下载 MySQL 压缩包 2.配置环境变量 3.创建配置文件my.ini (放置 mysql-5.7.28-winx64 目录下) my.ini 配置文件 编写如下内容 [client] p ...

  8. IAR平台移植TI OSAL到STC8A8K64S4A12单片机中

    玩过TI 的ZigBee或者BLE的人,都会接触到OSAL.OSAL是什么?OSAL英文全称:operating system abstraction layer(操作系统抽象层).基于OSAL的调度 ...

  9. 如何在C中以二进制格式打印十进制数?

    回答: #define CHAR_BITS  8  // size of character #define INT_BITS  ( sizeof(int) * CHAR_BITS) //bits i ...

  10. 关于Maven打包

    Maven打包构建完全指南和最佳实践 Maven最佳实践:划分模块 IDEA一个项目引用另一个项目 IDEA创建多个模块MavenSpringBoot项目   这个简单明了,基础知识