package com.lcjian.library.widget;
|
|
import android.content.Context;
|
import android.content.res.TypedArray;
|
import android.util.AttributeSet;
|
import android.view.View;
|
import android.view.animation.AnticipateInterpolator;
|
import android.view.animation.OvershootInterpolator;
|
import android.widget.FrameLayout;
|
import android.widget.ImageView;
|
|
import com.lcjian.lcjianlibrary.R;
|
import com.nineoldandroids.animation.Animator;
|
import com.nineoldandroids.animation.AnimatorListenerAdapter;
|
import com.nineoldandroids.animation.ObjectAnimator;
|
import com.nineoldandroids.animation.PropertyValuesHolder;
|
|
public class ArcMeun extends FrameLayout {
|
|
private float mFromDegrees;
|
private float mToDegrees;
|
private float mRadius;
|
private int mDuration;
|
private boolean closeOnClick;
|
private int mainImage;
|
|
private ImageView mainbtn;
|
|
private float[] translationXs;
|
private float[] translationYs;
|
|
public ArcMeun(Context context) {
|
this(context, null);
|
}
|
|
public ArcMeun(Context context, AttributeSet attrs) {
|
this(context, attrs, 0);
|
}
|
|
public ArcMeun(Context context, AttributeSet attrs, int defStyle) {
|
super(context, attrs, defStyle);
|
|
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ArcMenu, defStyle, 0);
|
|
mFromDegrees = a.getFloat(R.styleable.ArcMenu_fromDegrees, 180);
|
mToDegrees = a.getFloat(R.styleable.ArcMenu_toDegrees, 90);
|
mRadius = a.getDimensionPixelSize(R.styleable.ArcMenu_arcRadius, 100);
|
mDuration = a.getInteger(R.styleable.ArcMenu_duration, 300);
|
closeOnClick = a.getBoolean(R.styleable.ArcMenu_closeOnClick, true);
|
mainImage = a.getResourceId(R.styleable.ArcMenu_mainImage, 0);
|
|
a.recycle();
|
|
mainbtn = new ImageView(context);
|
mainbtn.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
|
mainbtn.setImageResource(mainImage);
|
addView(mainbtn);
|
}
|
|
@Override
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
if (Math.abs(mToDegrees - mFromDegrees) > 360) {
|
throw new IllegalStateException("angle must less than 360");
|
}
|
measureChildren(widthMeasureSpec, heightMeasureSpec);
|
translationXs = new float[getChildCount()];
|
translationYs = new float[getChildCount()];
|
for (int i = 0; i < getChildCount(); i++) {
|
translationXs[i] = (float) Math.sin(Math.toRadians(mFromDegrees + (mFromDegrees - mToDegrees) / (getChildCount() - 1) * i)) * mRadius;
|
translationYs[i] = (float) Math.cos(Math.toRadians(mFromDegrees + (mFromDegrees - mToDegrees) / (getChildCount() - 1) * i)) * mRadius;
|
}
|
float minTranslationX = getMin(translationXs);
|
float maxTranslationX = getMax(translationXs);
|
float minTranslationY = getMin(translationYs);
|
float maxTranslationY = getMax(translationYs);
|
|
setMeasuredDimension((int) (maxTranslationX - minTranslationX), (int) (maxTranslationY - minTranslationY));
|
}
|
|
@Override
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
super.onLayout(changed, left, top, right, bottom);
|
}
|
|
private float getMax(float[] arryas) {
|
if (arryas == null || arryas.length <= 0) {
|
return 0;
|
}
|
float max = arryas[0];
|
for (int i = 0; i < arryas.length; i++) {
|
if (max < arryas[i]) {
|
max = arryas[i];
|
}
|
}
|
return max;
|
}
|
|
private float getMin(float[] arryas) {
|
if (arryas == null || arryas.length <= 0) {
|
return 0;
|
}
|
float min = arryas[0];
|
for (int i = 0; i < arryas.length; i++) {
|
if (min > arryas[i]) {
|
min = arryas[i];
|
}
|
}
|
return min;
|
}
|
|
public void addMenuItem(View item, OnClickListener l) {
|
item.setOnClickListener(l);
|
addView(item);
|
mainbtn.bringToFront();
|
}
|
|
public void closeMeun() {
|
for (int i = 0; i < getChildCount(); i++) {
|
final View child = getChildAt(i);
|
PropertyValuesHolder propertyValuesHolderX = PropertyValuesHolder.ofFloat("translationX",
|
((float) Math.sin(Math.toRadians(mFromDegrees + (mFromDegrees - mToDegrees) / (getChildCount() - 1) * i)) * mRadius), 0);
|
PropertyValuesHolder propertyValuesHolderY = PropertyValuesHolder.ofFloat("translationY",
|
((float) Math.cos(Math.toRadians(mFromDegrees + (mFromDegrees - mToDegrees) / (getChildCount() - 1) * i)) * mRadius), 0);
|
PropertyValuesHolder propertyValuesHolderrotation = PropertyValuesHolder.ofFloat("rotation", 720, 0);
|
|
ObjectAnimator item = ObjectAnimator.ofPropertyValuesHolder(child,
|
propertyValuesHolderX, propertyValuesHolderY,
|
propertyValuesHolderrotation).setDuration(mDuration);
|
item.setStartDelay((getChildCount() - 1 - i) * 30);
|
item.setInterpolator(new AnticipateInterpolator(2));
|
item.addListener(new AnimatorListenerAdapter() {
|
@Override
|
public void onAnimationStart(Animator animation) {
|
child.setVisibility(View.VISIBLE);
|
}
|
@Override
|
public void onAnimationEnd(Animator animation) {
|
child.setVisibility(View.INVISIBLE);
|
}
|
});
|
item.start();
|
}
|
ObjectAnimator rotation = ObjectAnimator.ofFloat(mainbtn, "rotation", 135, 0);
|
rotation.start();
|
}
|
|
public void openMeun() {
|
for (int i = 0; i < getChildCount(); i++) {
|
final View child = getChildAt(i);
|
PropertyValuesHolder propertyValuesHolderX = PropertyValuesHolder.ofFloat("translationX", 0,
|
((float) Math.sin(Math.toRadians(mFromDegrees + (mFromDegrees - mToDegrees) / (getChildCount() - 1) * i)) * mRadius));
|
PropertyValuesHolder propertyValuesHolderY = PropertyValuesHolder.ofFloat("translationY", 0,
|
((float) Math.cos(Math.toRadians(mFromDegrees + (mFromDegrees - mToDegrees) / (getChildCount() - 1) * i)) * mRadius));
|
PropertyValuesHolder propertyValuesHolderrotation = PropertyValuesHolder.ofFloat("rotation", 0, 720);
|
|
ObjectAnimator item = ObjectAnimator.ofPropertyValuesHolder(child,
|
propertyValuesHolderX, propertyValuesHolderY,
|
propertyValuesHolderrotation).setDuration(mDuration);
|
item.setStartDelay(i * 30);
|
item.setInterpolator(new OvershootInterpolator(2));
|
item.addListener(new AnimatorListenerAdapter() {
|
@Override
|
public void onAnimationStart(Animator animation) {
|
child.setVisibility(View.VISIBLE);
|
}
|
});
|
item.start();
|
}
|
ObjectAnimator rotation = ObjectAnimator.ofFloat(mainbtn, "rotation", 0, 135);
|
rotation.start();
|
}
|
}
|