Android 弧形菜单设计

1.开发环境


Android Studio 3.0

Gradle版本:4.3

开发测试手机分辨率:720 * 1280

2.功能描述


弧形菜单布局使用常规布局模式也可以实现,但在手机分辨率众多,机型繁杂的情况下,这种自定义形状的菜单设计就需要自己精细雕琢。弧形菜单设计在网上文章非常多,本人结合自己设计经验,简单描述该功能重点实现部分,同时大多数文章只是在讲述如果实现自定义布局,而对于如何结合控件缩放实现此功能的文章基本上很难找到。

3.软件界面

Android 弧形菜单设计_第1张图片
image
Android 弧形菜单设计_第2张图片
image

自定义弧形菜单,继承ViewGroup,实现onMeasure和onLayout方法,同时为自定义控件添加菜单响应事件。

4.核心代码


protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec) {

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int measureWidth = measureWidth(widthMeasureSpec);

    int measureHeight = measureHeight(heightMeasureSpec);

    // 计算自定义的ViewGroup中所有子控件的大小

    measureChildren(widthMeasureSpec, heightMeasureSpec);

    // 设置自定义的控件MyViewGroup的大小

    setMeasuredDimension(measureWidth, measureHeight);

}

有一点非常重要:
l,t,r,b均指ViewGroup在软件屏幕中的位置,而childView.layout是以窗口所在区域为坐标体系的。

protected void onLayout(boolean changed,int l,int t,int r,int b) {

final int childCount = getChildCount();

//计算容器宽度和高度及内圈与外圈半径

    int viewWidth  = r - l;

int viewHeight = b - t;

int cx = (r + l)/2;

int cy = (t + b)/2;

int mRadius0 =0;

int mRadius1 =0;

mRadius0 = viewHeight/2 -20;//中间背景圆半径

    mRadius1 = mRadius0 + (viewWidth/2 - mRadius0)/2;//图标所在圆半径

    int iIconSize = mRadius0*2/3;//图标大小

    int mIntervalHeight =10;//图标之间间隔高度

    if ( (5 * iIconSize +120) > viewWidth)

{

iIconSize = (viewWidth -120)/5;

mRadius0 =3 * iIconSize/2;

}

mIntervalHeight = (viewHeight -2 * mRadius0)/4;

mRadius1 = mRadius0 + (viewWidth/2 - mRadius0)/2;

//确定摆放方向及

    int mLeft =0;

// 遍历子View

    for (int i =0; i < childCount; i++) {

View childView = getChildAt(i);

// 获得子View的高度

        int childViewHeight = childView.getMeasuredHeight();

// 获得子View的宽度

        int childViewWidth = childView.getMeasuredWidth();

if ( i ==0)

{

RelativeLayout.LayoutParams params  =new RelativeLayout.LayoutParams( mRadius0*2 , mRadius0*2);

childView.setLayoutParams(params);

childView.layout(cx - mRadius0, cy - mRadius0, cx + mRadius0, cy + mRadius0);

}

else if ( i ==1 || i==3 || i==4 || i==6)

{

RelativeLayout.LayoutParams params  =new RelativeLayout.LayoutParams( iIconSize , iIconSize);

childView.setLayoutParams(params);

//计算图标所在X位置

            int y0 = mIntervalHeight + iIconSize/2;

int x0 = (int)(viewWidth/2 - Math.sqrt( mRadius1 * mRadius1 - (viewHeight/2 - y0) * (viewHeight/2 - y0)));

if ( i==3)

{

y0 = viewHeight - y0;

}

else if ( i==4)

{

x0 = viewWidth - x0;

}

else if ( i ==6)

{

x0 = viewWidth - x0;

y0 = viewHeight - y0;

}

int x = x0 - iIconSize/2;

int y = y0 - iIconSize/2;

childView.layout(x, y, x + iIconSize, y + iIconSize);

}

else if ( i ==2 || i==5 )

{

RelativeLayout.LayoutParams params  =new RelativeLayout.LayoutParams( iIconSize , iIconSize);

childView.setLayoutParams(params);

//计算图标所在X位置

            int y0 = viewHeight/2;

int x0 = viewWidth/2 - mRadius1;

if ( i ==5)

{

x0 = viewWidth - x0;

}

int x = x0 - iIconSize/2;

int y = y0 - iIconSize/2;

childView.layout(x, y, x + iIconSize, y + iIconSize);

}

else if ( i ==7)

{

RelativeLayout.LayoutParams params  =new RelativeLayout.LayoutParams( iIconSize , iIconSize);

childView.setLayoutParams(params);

//计算图标所在X位置

            int y0 = viewHeight/2;

int x0 = viewWidth/2;

int x = x0 - iIconSize/2;

int y = y0 - iIconSize/2;

childView.layout(x, y, x + iIconSize, y + iIconSize);

}

}

}

5.总结

  布局容器中,每个图标位置和大小都需要考虑到,进行精确计算。

关键词: 弧形菜单,图标大小自适应变化,onMeasure,onLayout,自定义布局,自定义菜单设计

本文章提出解决此类问题的大概基本思路,若有源码需求请联系:[email protected]

你可能感兴趣的:(Android 弧形菜单设计)