直接上图:
SatelliteMenu.javaimport android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.RotateAnimation; import android.view.animation.ScaleAnimation; import android.view.animation.TranslateAnimation; /** * Created by Administrator on 2016/5/11. */ public class SatelliteMenu extends ViewGroup implements View.OnClickListener { /** * 卫星式菜单的四个位置 */ public static final int LEFT_TOP = 0; public static final int LEFT_BOTTOM = 1; public static final int RIGHT_TOP = 2; public static final int RIGHT_BOTTOM = 3; public static final int DEFAULT_RADIUS = 100; public float radius; //菜单的弧形半径 public Status status = Status.CLOSE; //菜单的开关状态 public Poisition position = Poisition.LEFT_BOTTOM; public OnSatelliteMenuItemClickListener onSateMenuClickListener; //点击菜单项事件回调的接口 /** * 枚举菜单位置 */ public enum Poisition { LEFT_TOP, LEFT_BOTTOM, RIGHT_TOP, RIGHT_BOTTOM } /** * 枚举菜单状态 */ public enum Status { OPEN, CLOSE } public interface OnSatelliteMenuItemClickListener { public void onClick(View view); } /** * 主菜单点击事件的重写 * @param v */ @Override public void onClick(View v) { RotateButton(v, 0f, 360f, 300); toggleMenuButton(300); } public void setOnSateMenuClickListener(OnSatelliteMenuItemClickListener onSateMenuClickListener) { this.onSateMenuClickListener = onSateMenuClickListener; } public SatelliteMenu(Context context) { this(context, null); } public SatelliteMenu(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SatelliteMenu(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); /** * 获取自定义属性 */ TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SatelliteLayout); int pos = typedArray.getInt(R.styleable.SatelliteLayout_position, RIGHT_BOTTOM); radius = typedArray.getDimension(R.styleable.SatelliteLayout_radius, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics())); Log.e("radius1", "" + radius); typedArray.recycle(); switch (pos) { case LEFT_TOP: position = Poisition.LEFT_TOP; break; case LEFT_BOTTOM: position = Poisition.LEFT_BOTTOM; break; case RIGHT_TOP: position = Poisition.RIGHT_TOP; break; case RIGHT_BOTTOM: position = Poisition.RIGHT_BOTTOM; break; } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int count = getChildCount(); for (int i = 0; i < count; i++) { // 测量child measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec); } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } /** * 确定各个菜单项的位置 * @param changed * @param l * @param t * @param r * @param b */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if (changed) { int childCount = getChildCount(); layoutCenterButton(getChildAt(0), position); for (int i = 1; i < childCount; i++) { View child = getChildAt(i); int childLeft = (int) (radius * Math.sin((i - 1) * Math.PI / 2 / (childCount - 2))); int childTop = (int) (radius * Math.cos((i - 1) * Math.PI / 2 / (childCount - 2))); if (position == Poisition.LEFT_TOP) { } else if (position == Poisition.LEFT_BOTTOM) { childTop = getMeasuredHeight() - childTop - child.getMeasuredHeight(); } else if (position == Poisition.RIGHT_TOP) { childLeft = getMeasuredWidth() - childLeft - child.getMeasuredWidth(); } else if (position == Poisition.RIGHT_BOTTOM) { childLeft = getMeasuredWidth() - childLeft - child.getMeasuredWidth(); childTop = getMeasuredHeight() - childTop - child.getMeasuredHeight(); } int childRight = childLeft + child.getMeasuredWidth(); int childBottom = childTop + child.getMeasuredHeight(); child.layout(childLeft, childTop, childRight, childBottom); child.setVisibility(GONE); } } } /** * 确定主菜单的位置 * @param centerButton * @param position */ public void layoutCenterButton(View centerButton, Poisition position) { centerButton.setOnClickListener(this); switch (position) { case LEFT_TOP: centerButton.layout(0, 0, centerButton.getMeasuredWidth(), centerButton.getMeasuredHeight()); break; case LEFT_BOTTOM: centerButton.layout(0, getMeasuredHeight() - centerButton.getMeasuredHeight(), centerButton.getMeasuredWidth(), getMeasuredHeight()); break; case RIGHT_TOP: centerButton.layout(getMeasuredWidth() - centerButton.getMeasuredWidth(), 0, getMeasuredWidth(), centerButton.getMeasuredHeight()); break; case RIGHT_BOTTOM: centerButton.layout(getMeasuredWidth() - centerButton.getMeasuredWidth(), getMeasuredHeight() - centerButton.getMeasuredHeight(), getMeasuredWidth(), getMeasuredHeight()); break; } } /** * 点击主菜单时的旋转动画 * @param v * @param start * @param end * @param during */ private void RotateButton(View v, float start, float end, long during) { RotateAnimation rotataAnimation = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotataAnimation.setFillAfter(true); rotataAnimation.setDuration(during); v.startAnimation(rotataAnimation); } /** * 点击主菜单弹出或收回菜单项 * @param during */ private void toggleMenuButton( int during) { int childCount = getChildCount(); for (int i = 1; i < childCount; i++) { final View child = getChildAt(i); child.setVisibility(VISIBLE); int childLeft = (int) (radius * Math.sin((i - 1) * Math.PI / 2 / (childCount - 2))); int childTop = (int) (radius * Math.cos((i - 1) * Math.PI / 2 / (childCount - 2))); int xflag = 1; int yflag = 1; if (position == Poisition.LEFT_TOP || position == Poisition.RIGHT_TOP) { yflag = -1; } if (position == Poisition.LEFT_TOP || position == Poisition.LEFT_BOTTOM) { xflag = -1; } AnimationSet animationSet = new AnimationSet(true); Animation traAnimation = null; //to close if (status == Status.CLOSE) { traAnimation = new TranslateAnimation(xflag * childLeft, 0, yflag * childTop, 0); child.setFocusable(true); child.setClickable(true); } //to close if (status == Status.OPEN) { traAnimation = new TranslateAnimation(0, xflag * childLeft, 0, yflag * childTop); child.setFocusable(false); child.setClickable(false); } traAnimation.setDuration(during); traAnimation.setFillAfter(true); traAnimation.setStartOffset(i * 100/childCount); traAnimation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { if (status == Status.CLOSE) { child.setVisibility(GONE); } } @Override public void onAnimationRepeat(Animation animation) { } }); RotateAnimation childRotateAnimation = new RotateAnimation(0, 720, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); childRotateAnimation.setFillAfter(true); childRotateAnimation.setDuration(during); animationSet.addAnimation(childRotateAnimation); animationSet.addAnimation(traAnimation); child.startAnimation(animationSet); child.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if(onSateMenuClickListener!=null){ onSateMenuClickListener.onClick(v); } addChildAnimation(300,v); changeStatus(); } }); } changeStatus(); } /** * 添加mennuitem的点击动画 * @param during * @param */ public void addChildAnimation(int during ,View view){ int count=getChildCount(); for(int i=1;i<count;i++){ View child=getChildAt(i); if(child==view){ child.startAnimation(scaleBigMenuItem(during)); }else { child.startAnimation(scaleSmallMenuItem(during)); } child.setClickable(false); child.setFocusable(false); } } /** * 菜单项的缩小动画 * @param during * @return */ public Animation scaleSmallMenuItem(int during){ AnimationSet animationSet = new AnimationSet(true); ScaleAnimation scaleAnimation= new ScaleAnimation(1.0f, 0.0f, 1.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f,0f); animationSet.addAnimation(scaleAnimation); animationSet.addAnimation(alphaAnimation); animationSet.setDuration(during); animationSet.setFillAfter(true); return animationSet; } /** * 菜单项的放大动画 * @param during * @return */ public Animation scaleBigMenuItem(int during){ AnimationSet animationSet = new AnimationSet(true); ScaleAnimation scaleAnimation= new ScaleAnimation(1.0f, 4.0f, 1.0f, 4.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f,0f); animationSet.addAnimation(scaleAnimation); animationSet.addAnimation(alphaAnimation); animationSet.setDuration(during); animationSet.setFillAfter(true); return animationSet; } /** * 改变菜单项的展开收缩状态 */ public void changeStatus() { status = (status == Status.CLOSE ? Status.OPEN : Status.CLOSE); } }