偶然看到Path的动画很炫酷,所以摸索写了一个,无非是一个主按钮+卫星按钮,摆放好位置即可。
本来想写成一个拓展性的,结果脑袋卡壳半天不知道怎么写,所以还是贴一个固定位置的,有时间在改吧。
动画效果:位移+旋转+透明
点击效果:放大+透明(没做)
效果图
代码比较简单,直接贴
package com.zhou.pathbuttonview;
import java.util.ArrayList;
import java.util.List;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
public class SimpleActivity extends Activity implements OnClickListener {
private ImageView home, top, topleft, topleftleft, topright, toprightright;
private List<ImageView> list = new ArrayList<ImageView>();
private List<ObjectAnimator> anim_list = new ArrayList<ObjectAnimator>();
private boolean home_flag = true, isFirst = true;// 卫星按钮打开关闭, 卫星按钮设置是否显示
private int startX, startY;// 主按钮位置
private RotateAnimation homeStartAnim, homeBackAnim;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
init();
addListener();
}
private void init() {
home = (ImageView) findViewById(R.id.home);
top = (ImageView) findViewById(R.id.top);
topleft = (ImageView) findViewById(R.id.topleft);
topleftleft = (ImageView) findViewById(R.id.topleftleft);
topright = (ImageView) findViewById(R.id.topright);
toprightright = (ImageView) findViewById(R.id.toprightright);
// 主按钮旋转动画
homeStartAnim = new RotateAnimation(0, -135.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
homeStartAnim.setDuration(150);
homeStartAnim.setFillAfter(true);
homeBackAnim = new RotateAnimation(-135.0f, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
homeBackAnim.setDuration(150);
homeBackAnim.setFillAfter(true);
list.add(topleftleft);
list.add(topleft);
list.add(top);
list.add(topright);
list.add(toprightright);
// 隐藏卫星按钮
for (int i = 0; i < 5; i++) {
list.get(i).setVisibility(View.INVISIBLE);
}
}
private void addListener() {
home.setOnClickListener(this);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
// 获取home的坐标,作为展开时的起点/收缩时的终点
int[] startXY = new int[2];
home.getLocationOnScreen(startXY);
startX = startXY[0] + home.getMeasuredWidth() / 2;
startY = startXY[1] + home.getMeasuredWidth() / 2;
for (int i = 0; i < list.size(); i++) {
initStartAnimatorSet(list.get(i));// 初始化展开动画
}
for (int i = 0; i < list.size(); i++) {
initFinishAnimatorSet(list.get(i));// 初始化收缩动画
}
super.onWindowFocusChanged(hasFocus);
}
// 坐标(0,0)是指view本身为原点,两view坐标差值为伸缩值。
// 展开动画
private void initStartAnimatorSet(View view) {
int[] location = new int[2];
view.getLocationOnScreen(location);
ObjectAnimator set = getObjectAnimator(view, startX - view.getWidth() / 2 - location[0], 0,
startY - view.getHeight() / 2 - location[1], 0, -360, 0f, 1f, 600);
anim_list.add(set);
}
// 收缩动画
private void initFinishAnimatorSet(View view) {
int[] location = new int[2];
view.getLocationOnScreen(location);
ObjectAnimator set = getObjectAnimator(view, 0, startX - view.getWidth() / 2 - location[0], 0,
startY - view.getHeight() / 2 - location[1], 360, 1f, 0f, 600);
anim_list.add(set);
}
// 下面(startX, startX, endX,endX)写两次就是让它在外面多旋一会,最好是 (startX, startX, endX)
/**
*
* @param view
* 传入的子view
* @param startX
* 起始位置X
* @param endX
* 结束位置X
* @param startY
* 起始位置Y
* @param endY
* 结束位置Y
* @param degree
* 旋转角度
* @param startA
* 开始透明度
* @param endA
* 结束透明度
* @param time
* 动画持续时间
* @return
*/
private ObjectAnimator getObjectAnimator(View view, float startX, float endX, float startY, float endY,
float degree, float startA, float endA, long time) {
PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX", startX, startX, endX, endX);
PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("translationY", startY, startY, endY, endY);
PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("rotation", degree);
PropertyValuesHolder pvh4 = PropertyValuesHolder.ofFloat("alpha", startA, endA);
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(view, pvh1, pvh2, pvh3, pvh4)
.setDuration(time);
return objectAnimator;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.simple, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View v) {
int id = v.getId();
if (R.id.home == id) {
if (home_flag) {
home.startAnimation(homeStartAnim);
//第一次 让卫星按钮显示出来
if (isFirst) {
for (int j = 0; j < 5; j++) {
list.get(j).setVisibility(View.VISIBLE);
}
isFirst = false;
}
for (int i = 0; i < 5; i++) {
anim_list.get(i).start();
}
home_flag = false;
} else {
home.startAnimation(homeBackAnim);
for (int i = 5; i < 10; i++) {
anim_list.get(i).start();
}
home_flag = true;
}
}
}
}
布局文件
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#EED8AE" >
<ImageView
android:id="@+id/top"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_above="@+id/home"
android:layout_centerHorizontal="true"
android:layout_marginBottom="40dp"
android:background="@drawable/shape_pathbutton"
android:contentDescription="@string/app_name"
android:scaleType="centerInside"
android:src="@drawable/home" />
<ImageView
android:id="@+id/topleft"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_above="@+id/home"
android:layout_centerHorizontal="true"
android:layout_marginBottom="30dp"
android:layout_marginRight="15dp"
android:layout_toLeftOf="@+id/top"
android:background="@drawable/shape_pathbutton"
android:contentDescription="@string/app_name"
android:scaleType="centerInside"
android:src="@drawable/light" />
<ImageView
android:id="@+id/topleftleft"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_above="@+id/home"
android:layout_centerHorizontal="true"
android:layout_marginRight="8dp"
android:layout_toLeftOf="@+id/topleft"
android:background="@drawable/shape_pathbutton"
android:contentDescription="@string/app_name"
android:scaleType="centerInside"
android:src="@drawable/download" />
<ImageView
android:id="@+id/topright"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_above="@+id/home"
android:layout_centerHorizontal="true"
android:layout_marginBottom="30dp"
android:layout_marginLeft="15dp"
android:layout_toRightOf="@+id/top"
android:background="@drawable/shape_pathbutton"
android:contentDescription="@string/app_name"
android:scaleType="centerInside"
android:src="@drawable/setting" />
<ImageView
android:id="@+id/toprightright"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_above="@+id/home"
android:layout_centerHorizontal="true"
android:layout_marginLeft="8dp"
android:layout_toRightOf="@+id/topright"
android:background="@drawable/shape_pathbutton"
android:contentDescription="@string/app_name"
android:scaleType="centerInside"
android:src="@drawable/location" />
<ImageView
android:id="@+id/home"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp"
android:background="@drawable/bg_pathhome"
android:contentDescription="@string/app_name"
android:scaleType="centerCrop"
android:src="@drawable/add" />
</RelativeLayout>
在 drawable自定义两个shape就是一个圆,大小不一样而已,这里贴一个
shape_pathbutton
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<corners
android:bottomLeftRadius="15dip"
android:bottomRightRadius="15dip"
android:topLeftRadius="15dip"
android:topRightRadius="15dip" />
<stroke
android:width="1px"
android:color="@android:color/black" />
<solid android:color="#DEDEDE" />
</shape>
另一个类似,不贴了。