介绍
本文主要介绍一个菜单的主要实现步骤 下面是效果图
实现步骤
ArcMenu.java
public class ArcMenu extends ViewGroup implements View.OnClickListener {
private static final int RADIUS = 300;
private CurrentState state;
private enum CurrentState {
OPEN, CLOSE
}
public ArcMenu(Context context, AttributeSet attrs) {
super(context, attrs);
state = CurrentState.CLOSE;
}
// ViewGroup默认只测量自身,不测量孩子
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//先测量孩子
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).measure(0, 0);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//测量viewgroup
int width = (RADIUS + getChildAt(getChildCount() - 1).getMeasuredWidth());
int height = (RADIUS + getChildAt(1).getMeasuredWidth());
setMeasuredDimension(width, height);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
View child0 = getChildAt(0);
child0.setOnClickListener(this);
child0.layout(0, 0, child0.getMeasuredWidth(), child0.getMeasuredHeight());
int count = getChildCount();
for (int i = 0; i < count - 1; i++) {
// 孩子的左边距=第0个孩子与当前孩子的连线与垂直的半径的夹角的正弦值*半径
int childLeft = (int) (RADIUS * Math.sin(Math.PI / 2 / (count - 2) * i));
int childRight = childLeft + getChildAt(i + 1).getMeasuredWidth();
int childTop = (int) (RADIUS * Math.cos(Math.PI / 2 / (count - 2) * i));
int childBottom = childTop + getChildAt(i + 1).getMeasuredHeight();
getChildAt(i + 1).layout(childLeft, childTop, childRight, childBottom);
getChildAt(i+1).setVisibility(View.INVISIBLE);
}
}
//控制开关
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.rl:
Toast.makeText(getContext(), "哈哈", Toast.LENGTH_SHORT).show();
rotateFirst();
rotateOtherChildren();
break;
default:
break;
}
}
private void rotateOtherChildren() {
for (int i = 0; i < getChildCount() - 1; i++) {
AnimationSet set = new AnimationSet(false);
final View child = getChildAt(i + 1);
int childLeft = child.getLeft();
int childTop = child.getTop();
TranslateAnimation ta;
if (state == CurrentState.OPEN) {
// 绝对移动,起始点的位置为0
ta = new TranslateAnimation(TranslateAnimation.ABSOLUTE, 0, TranslateAnimation.ABSOLUTE, -childLeft, TranslateAnimation.ABSOLUTE, 0, TranslateAnimation.ABSOLUTE,
-childTop);
} else {
ta = new TranslateAnimation(TranslateAnimation.ABSOLUTE, -childLeft, TranslateAnimation.ABSOLUTE, 0, TranslateAnimation.ABSOLUTE, -childTop,
TranslateAnimation.ABSOLUTE, 0);
}
ta.setDuration(2000);
ta.setFillAfter(true);
// 设置动画开始的偏移时间
ta.setStartOffset(i * 200);
ta.setInterpolator(new OvershootInterpolator());
RotateAnimation ra = new RotateAnimation(0, 360, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
ra.setDuration(2000);
ra.setFillAfter(true);
// 在动画集合中先添加ta,再添加ra,在执行的过程中,中心点会一直改变
set.addAnimation(ra);
set.addAnimation(ta);
child.startAnimation(set);
set.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
if(state==CurrentState.OPEN){
child.setVisibility(View.VISIBLE);
}else{
child.setVisibility(View.INVISIBLE);
}
}
});
}
//改变状态
changeState();
}
private void changeState() {
state=state==CurrentState.CLOSE?CurrentState.OPEN:CurrentState.CLOSE;
}
private void rotateFirst() {
RotateAnimation ra = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
ra.setDuration(2000);
ra.setFillAfter(true);
getChildAt(0).startAnimation(ra);
}
}
对应的布局文件
<mgzxc.arcmenu.ArcMenu
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<RelativeLayout
android:id="@+id/rl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/composer_button" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/composer_icn_plus" />
</RelativeLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/composer_camera" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/composer_music" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/composer_place" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/composer_sleep" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/composer_sun" />
</mgzxc.arcmenu.ArcMenu>