您的位置:首页 > 移动开发 > Android开发

【Android界面实现】实现底部扇形展开菜单效果

2014-03-11 10:43 701 查看
先看效果图





项目的总结构



下面开始贴代码,由于必要的地方都添加了注释,所以不过多讲解

anim_button.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >

<Button
android:id="@+id/btn_sleep"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:visibility="invisible"
android:background="@drawable/composer_sleep" />

<Button
android:id="@+id/btn_thought"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:visibility="invisible"
android:background="@drawable/composer_thought" />

<Button
android:id="@+id/btn_music"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:visibility="invisible"
android:background="@drawable/composer_music" />

<Button
android:id="@+id/btn_place"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:visibility="invisible"
android:background="@drawable/composer_place" />

<Button
android:id="@+id/btn_with"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:visibility="invisible"
android:background="@drawable/composer_with" />

<Button
android:id="@+id/btn_camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:visibility="invisible"
android:background="@drawable/composer_camera" />

<Button
android:id="@+id/btn_menu"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:background="@drawable/friends_delete" />

</RelativeLayout>


主界面的布局main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<com.example.anim.AnimButtons
android:id="@+id/animButtons"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>


最重要的,自定义控件的实现

AnimButtons.java

package com.example.anim;

import android.R.anim;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.RelativeLayout;

/**
* 底部展开菜单实现
*
* @author ZhaoKaiQiang
*
*         Time:2014年3月11日
*/
public class AnimButtons extends RelativeLayout {

private Context context;
private int leftMargin = 0, bottomMargin = 0;
private final int buttonWidth = 58;// 图片宽高
private final int r = 180;// 半径
private final int maxTimeSpent = 200;// 最长动画耗时
private final int minTimeSpent = 80;// 最短动画耗时
private int intervalTimeSpent;// 每相邻2个的时间间隔
private Button[] btns;
private Button btn_menu;
private RelativeLayout.LayoutParams params;
private boolean isOpen = false;// 是否菜单打开状态
private float angle;// 每个按钮之间的夹角

public int bottomMargins = this.getMeasuredHeight() - buttonWidth
- bottomMargin;

public AnimButtons(Context context) {
super(context);
this.context = context;
}

public AnimButtons(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}

@Override
protected void onFinishInflate() {
super.onFinishInflate();
View view = LayoutInflater.from(context).inflate(R.layout.anim_buttons,
this);

initButtons(view);

}

private void initButtons(View view) {
// 可以根据按钮的个数自己增减
btns = new Button[4];
btns[0] = (Button) view.findViewById(R.id.btn_camera);
btns[1] = (Button) view.findViewById(R.id.btn_with);
btns[2] = (Button) view.findViewById(R.id.btn_place);
btns[3] = (Button) view.findViewById(R.id.btn_music);
// btns[4] = (Button) view.findViewById(R.id.btn_thought);
// btns[5] = (Button) view.findViewById(R.id.btn_sleep);
btn_menu = (Button) view.findViewById(R.id.btn_menu);

leftMargin = ((RelativeLayout.LayoutParams) (btn_menu.getLayoutParams())).leftMargin;
bottomMargin = ((RelativeLayout.LayoutParams) (btn_menu
.getLayoutParams())).bottomMargin;

for (int i = 0; i < btns.length; i++) {
// 初始化的时候按钮重合
btns[i].setLayoutParams(btn_menu.getLayoutParams());
btns[i].setTag(String.valueOf(i));
btns[i].setOnClickListener(clickListener);
}

intervalTimeSpent = (maxTimeSpent - minTimeSpent) / btns.length;
angle = (float) Math.PI / (2 * (btns.length - 1));
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
bottomMargins = this.getMeasuredHeight() - buttonWidth - bottomMargin;
btn_menu.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
if (!isOpen) {
openMenu();
} else {
closeMenu();
}
}
});

}

public void closeMenu() {
if (isOpen == true) {
isOpen = false;
for (int i = 0; i < btns.length; i++) {
float xLenth = (float) (r * Math.sin(i * angle));
float yLenth = (float) (r * Math.cos(i * angle));
btns[i].startAnimation(animTranslate(-xLenth, yLenth,
leftMargin, bottomMargins, btns[i], maxTimeSpent - i
* intervalTimeSpent));
btns[i].setVisibility(View.INVISIBLE);
}
}
}

public void openMenu() {
isOpen = true;
for (int i = 0; i < btns.length; i++) {
float xLenth = (float) (r * Math.sin(i * angle));
float yLenth = (float) (r * Math.cos(i * angle));
btns[i].startAnimation(animTranslate(xLenth, -yLenth, leftMargin
+ (int) xLenth, bottomMargins - (int) yLenth, btns[i],
minTimeSpent + i * intervalTimeSpent));
btns[i].setVisibility(View.VISIBLE);
}

}

private Animation animScale(float toX, float toY) {
Animation animation = new ScaleAnimation(1.0f, toX, 1.0f, toY,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
animation.setInterpolator(context,
anim.accelerate_decelerate_interpolator);
animation.setDuration(400);
animation.setFillAfter(false);
return animation;

}

private Animation animTranslate(float toX, float toY, final int lastX,
final int lastY, final Button button, long durationMillis) {
Animation animation = new TranslateAnimation(0, toX, 0, toY);
animation.setAnimationListener(new AnimationListener() {

@Override
public void onAnimationStart(Animation animation) {

}

@Override
public void onAnimationRepeat(Animation animation) {

}

@Override
public void onAnimationEnd(Animation animation) {
params = new RelativeLayout.LayoutParams(0, 0);
params.height = buttonWidth;
params.width = buttonWidth;
params.setMargins(lastX, lastY, 0, 0);
button.setLayoutParams(params);
button.clearAnimation();

}
});
animation.setDuration(durationMillis);
return animation;
}

View.OnClickListener clickListener = new View.OnClickListener() {

@Override
public void onClick(View v) {
int selectedItem = Integer.parseInt((String) v.getTag());
for (int i = 0; i < btns.length; i++) {
if (i == selectedItem) {
btns[i].startAnimation(animScale(2.0f, 2.0f));
} else {
btns[i].startAnimation(animScale(0.0f, 0.0f));
}
}
if (onButtonClickListener != null) {
onButtonClickListener.onButtonClick(v, selectedItem);
}
}

};

public boolean isOpen() {
return isOpen;
}

private OnButtonClickListener onButtonClickListener;

public interface OnButtonClickListener {
void onButtonClick(View v, int id);
}

public void setOnButtonClickListener(
OnButtonClickListener onButtonClickListener) {
this.onButtonClickListener = onButtonClickListener;
}

}

AnimButtonsActivity.java

package com.example.anim;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
/**
* 主界面
* @author 	ZhaoKaiQiang
*
*			Time:2014年3月11日
*/
public class AnimButtonsActivity extends Activity {

private AnimButtons animButtons;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
animButtons = (AnimButtons) findViewById(R.id.animButtons);
animButtons
.setOnButtonClickListener(new AnimButtons.OnButtonClickListener() {
@Override
public void onButtonClick(View v, int id) {
Toast.makeText(AnimButtonsActivity.this, "id-->" + id,
0).show();
animButtons.closeMenu();
}
});
}
}

点击下载源码

如有问题,请留言
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  menu 扇形菜单