Android 弧形菜单设计

1.开发环境


Android Studio 3.0

Gradle版本:4.3

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

2.功能描述


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

3.软件界面

image
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,自定义布局,自定义菜单设计

本文章提出解决此类问题的大概基本思路,若有源码需求请联系:wjqxjtu@163.com

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容

  • 1.开发环境 Android Studio 3.0 Gradle版本:4.3 开发测试手机分辨率:720 * 12...
    硕之华阅读 1,196评论 0 0
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,907评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,709评论 2 59
  • 一个人,, 淡然笑_ce8 姓名:李文 公司名称:宁波大发化纤有限公司 《幸福精进》学习营第41期感谢组 【今日经...
    淡然笑_ce8e阅读 151评论 0 0
  • 在我的生命中再次迎来了让多少情人恋人们期盼的日子,而我的心情是失落的,因为我亲爱的老公为了养家糊口要出去挣钱工作,...
    高大超高星灿妈妈阅读 189评论 0 2