Android UI之半圆式卫星菜单(无动画)

飞夜羽博客从今天起,正式启动了,欢迎大家关注,多多捧场!以后会写一些在项目中遇到的难题以及解决方案,不会仅仅局限在知识方面,可能有写贴代码的方式及博客图片处理不熟悉,各位轻喷


最近在做项目时,遇到有客户提要求,希望做出如下的半圆式卫星菜单,楼主查阅了好多资料,终于不负苦心人做出来了

话不多说,直接上代码


自定义一个类

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定义较多,还请各位见谅

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值