飞夜羽博客从今天起,正式启动了,欢迎大家关注,多多捧场!以后会写一些在项目中遇到的难题以及解决方案,不会仅仅局限在知识方面,可能有写贴代码的方式及博客图片处理不熟悉,各位轻喷
最近在做项目时,遇到有客户提要求,希望做出如下的半圆式卫星菜单,楼主查阅了好多资料,终于不负苦心人做出来了
话不多说,直接上代码
自定义一个类
import 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.Animation.AnimationListener;
import android.view.animation.AnimationSet;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import com.fei.changrong.R;
public class ArcMenu extends ViewGroup{
private static final int POSITION_LEFT_TOP = 0;
private static final int POSITION_LEFT_BOTTOM = 1;
private static final int POSITION_RIGHT_TOP = 2;
private static final int POSITION_RIGHT_BOTTOM = 3;
private static final int POSITION_CENTER_BOTTOM = 4;
private static final int POSITION_CENTER_LEFT = 5;
//中心按钮所在位置
private Position mPosition = Position.CENTER_LEFT;
private int mRadius;
//中心按钮
private View mCButton;
//监听事件
private OnMenuItemClickListener mOnMenuItemClickListener;
//中心按钮所在位置
public enum Position {
LEFT_TOP, LEFT_BOTTOM, RIGHT_TOP, RIGHT_BOTTOM, CENTER_BOTTOM, CENTER_LEFT
}
public enum Status {
IS_OPEN
}
//功能描述 点击子菜单的回调接口
public interface OnMenuItemClickListener {
void onClick(View view, int position);
}
public ArcMenu(Context context) {
this(context, null);
}
public ArcMenu(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ArcMenu(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
100, getResources().getDisplayMetrics());
// 获取自定义属性的值
TypedArray typedArray = context.getTheme().obtainStyledAttributes(
attrs, R.styleable.ArcMenu, defStyle, 0);
int position = typedArray.getInt(R.styleable.ArcMenu_position,
POSITION_RIGHT_BOTTOM);
switch (position) {
case POSITION_LEFT_TOP:
mPosition = Position.LEFT_TOP;
break;
case POSITION_LEFT_BOTTOM:
mPosition = Position.LEFT_BOTTOM;
break;
case POSITION_RIGHT_TOP:
mPosition = Position.RIGHT_TOP;
break;
case POSITION_RIGHT_BOTTOM:
mPosition = Position.RIGHT_BOTTOM;
break;
case POSITION_CENTER_BOTTOM:
mPosition = Position.CENTER_BOTTOM;
break;
case POSITION_CENTER_LEFT:
mPosition = Position.CENTER_LEFT;
break;
default:
break;
}
mRadius = (int) typedArray.getDimension(R.styleable.ArcMenu_radius,
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100,
getResources().getDisplayMetrics()));
Log.v("tag", "position=" + position + ",mRadius=" + mRadius);
typedArray.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int count = getChildCount();
for (int i = 0; i < count; i++) {
measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed) {
layoutCButton();
layoutMenuItems();
}
}
//布局菜单项
private void layoutMenuItems() {
int count = getChildCount();
for (int i = 0; i < count - 1; i++) {
View child = getChildAt(i + 1);
int l = 0;
int t = 0;
int width = child.getMeasuredWidth();
int height = child.getMeasuredHeight();
//计算按钮位值
if (mPosition == Position.CENTER_BOTTOM) {
t = (int) (mRadius * Math.sin(Math.PI / count * (i + 1)));
l = (int) (mRadius * Math.cos(Math.PI / count * (i + 1)));
} else {
l = (int) (mRadius * Math.sin(Math.PI / 2 / (count - 2) * i));
t = (int) (mRadius * Math.cos(Math.PI / 2 / (count - 2) * i));
}
if(mPosition ==Position.CENTER_LEFT){
t=(int) (mRadius * Math.cos(Math.PI / count * (i + 1)));
l=(int) (mRadius * Math.sin(Math.PI / count * (i + 1)));
}else{
t = (int) (mRadius * Math.sin(Math.PI / 2 / (count - 2) * i));
l = (int) (mRadius * Math.cos(Math.PI / 2 / (count - 2) * i));
}
if (mPosition == Position.RIGHT_TOP
|| mPosition == Position.RIGHT_BOTTOM) {
l = getMeasuredWidth() - width - l;
}
if (mPosition == Position.LEFT_BOTTOM
|| mPosition == Position.RIGHT_BOTTOM) {
t = getMeasuredHeight() - height - t;
}
if (mPosition == Position.CENTER_BOTTOM) {
l = getMeasuredWidth() / 2 - width / 2 - l;
t = getMeasuredHeight() - height - t;
}
if (mPosition == Position.CENTER_LEFT) {
t = getMeasuredHeight() / 2 - height / 2 - t;
}
child.layout(l, t, l + width, t + height);
}
}
// 定位主菜单按钮
private void layoutCButton() {
mCButton = getChildAt(0);
toggleMenu();
int l = 0;
int t = 0;
int width = mCButton.getMeasuredWidth();
int height = mCButton.getMeasuredHeight();
switch (mPosition) {
case LEFT_TOP:
l = 0;
t = 0;
break;
case LEFT_BOTTOM:
l = 0;
t = getMeasuredHeight() - height;
break;
case RIGHT_TOP:
l = getMeasuredWidth() - width;
t = 0;
break;
case RIGHT_BOTTOM:
l = getMeasuredWidth() - width;
t = getMeasuredHeight() - height;
break;
case CENTER_BOTTOM:
l = getMeasuredWidth() / 2 - width / 2;
t = getMeasuredHeight() - height;
break;
case CENTER_LEFT:
l = 0;
t = getMeasuredHeight() / 2 - width / 2;
break;
}
mCButton.layout(l, t, l + width, t + height);
}
private void toggleMenu() {
int count = getChildCount();
for (int i = 0; i < count - 1; i++) {
final View childView = getChildAt(i + 1);
childView.setVisibility(View.VISIBLE);
final int pos = i + 1;
childView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (mOnMenuItemClickListener != null) {
mOnMenuItemClickListener.onClick(view, pos);
}
}
});
}
}
public void setmOnMenuItemClickListener(
OnMenuItemClickListener mOnMenuItemClickListener) {
this.mOnMenuItemClickListener = mOnMenuItemClickListener;
}
}
至此,自定义的菜单已经完成,下面,贴一下在Activity中的运用,中心按钮好像被覆盖住了,所以楼主投机的写了一个按钮,再次把中心按钮覆盖住,这样中心的按钮就可以做点击事件了,这点暂时还没找到解决办法,
private ArcMenu id_arcmenu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.satellite_menu);
id_arcmenu = (ArcMenu) findViewById(R.id.id_arcmenu);
}
private void initEvent() {
id_arcmenu.setmOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public void onClick(View view, int position) {
Intent intent = new Intent();
switch (position) {
case 1:
intent.setClass(MainActivity.this,
AssociateBarcodeList.class);
startActivity(intent);
break;
case 2:
intent.setClass(MainActivity.this, MyMessage.class);
startActivity(intent);
break;
case 3:
intent.setClass(MainActivity.this, QueryProduct.class);
startActivity(intent);
break;
case 4:
intent.setClass(MainActivity.this, ApplyMaintanence.class);
startActivity(intent);
break;
case 5:
intent.setClass(MainActivity.this, MaintanenceRecord.class);
startActivity(intent);
break;
case 6:
intent.setClass(MainActivity.this, Setting.class);
startActivity(intent);
break;
case 7:
intent.setClass(MainActivity.this, MainUser.class);
startActivity(intent);
break;
default:
break;
}
}
});
接着是咱们的XML的布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:hyman="http://schemas.android.com/apk/res/com.fei.changrong"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:background="@drawable/main_function_back" >
/*此处要将center_left写入value的attr文件中,不然获取不到哦*/
<com.fei.changrong.view.ArcMenu
android:id="@+id/id_arcmenu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:background="@drawable/function_page"
hyman:position="center_left"
hyman:radius="230dp" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/round_shape"
android:gravity="center" >
<ImageView
android:id="@+id/id_button"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_centerInParent="true"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:src="@drawable/msg_center" />
</RelativeLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/relative_barcode" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/query_msg" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/query_product" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/sale_server" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/fix_record" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/system_setting" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/personal_setting" />
</com.fei.changrong.view.ArcMenu>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:background="@drawable/round_shape"
android:gravity="center" >
<ImageView
android:id="@+id/img_msg_main"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_centerInParent="true"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:src="@drawable/msg_center" />
<TextView
android:id="@+id/tv_msg_num"
android:layout_width="25dip"
android:layout_height="25dip"
android:layout_above="@+id/img_msg_main"
android:layout_marginBottom="-30dp"
android:layout_marginLeft="-30dp"
android:layout_toRightOf="@+id/img_msg_main"
android:background="@drawable/red_msg"
android:gravity="center"
android:text="1"
android:textColor="@color/white"
android:textStyle="bold"
android:visibility="gone" />
</RelativeLayout>
</RelativeLayout>
最后贴一下attr的源码
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="position">
<enum name="left_top" value="0"/>
<enum name="left_bottom" value="1"/>
<enum name="right_top" value="2"/>
<enum name="right_bottom" value="3"/>
<enum name="center_bottom" value="4"/>
<enum name="center_left" value="5"/>
</attr>
<attr name="radius" format="dimension"/>
<declare-styleable name="ArcMenu">
<attr name="position"/>
<attr name="radius"/>
</declare-styleable>
</resources>
因为是楼主从项目上粘贴下来的代码,可能有部分UI定义较多,还请各位见谅