安卓自定义半圆弧形菜单
Posted yhongm
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓自定义半圆弧形菜单相关的知识,希望对你有一定的参考价值。
安卓开发自定义ViewGroup实现半圆弧形菜单 ,可实时修改菜单按钮数量,效果如下
使用方法
1.布局文件添加一下属性:
<com.yhongm.arcmenu.ArcMenu
app:main_btn_img="@drawable/main_btn" //中心按钮的背景
android:id="@+id/arcMenu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"></com.yhongm.arcmenu.ArcMenu>
2.java方法:
arcMenu.addChildArcMenu(当前添加子按钮图片资源id,按钮标题,按钮附带的额外信息可以为空)//添加新按钮的方法
arcMenu.layoutChildMenu()//初始化菜单
arcMenu.setShowMenuBtnNum(子按钮显示数量)//设置当前菜单显示子按钮的数量
arcMenu.setOnMenuItemClickListener(this) 设置点击按钮的监听
用到的知识点
- 三角函数,通过三角函数计算子按钮的坐标
- 自定义ViewGroup,onLayout摆放子按钮的位置
教程
一.onMeasure:
在onMeasure过程中测量子View,防止获取不到子View的宽高
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
for (int i = 0; i < getChildCount(); i++)
View childView = getChildAt(i);
measureChild(childView,widthMeasureSpec,heightMeasureSpec);
childView.measure(0, 0);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
二.onLayout:
1.在onLayout过程中摆放主按钮的位置,以及各个子按钮的位置
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
Log.i("ArcMenu", "onLayout,");// yuhongmiao 2017/6/6 下午7:49
if (changed)
layoutMainButton();//中间主按钮的摆放
layoutChildButtonToggleMenu(300);//子按钮的摆放与子按钮的点击动画处理
2.主按钮的摆放与主按钮的点击事件
/**
* 摆放主按钮,设置主按钮的点击事件
*/
private void layoutMainButton()
cButton = getChildAt(0);
cButton.setOnClickListener(this);
int l = 0;
int t = 0;
int width = cButton.getMeasuredWidth();
int height = cButton.getMeasuredHeight();
l = getMeasuredWidth() / 2 - width / 2;
t = (getMeasuredHeight() - 100) - height / 2;
cButton.layout(l, t, l + width, t + height);
3.各个子按钮的摆放,根据当前设置的显示按钮的数量实时计算每个按钮所占用的角度,通过三角函数计算每个子按钮的横纵坐标摆放
/**
* 按钮子按钮的布局与动画
*
* @param durationMillis
*/
private void layoutChildButtonToggleMenu(int durationMillis)
setBackgroundColor(Color.parseColor("#66111111"));
for (int i = 0; i < showMenuBtnNum; i++) //遍历要显示的子按钮
View childView = getChildAt(i + 1);
childView.setVisibility(View.VISIBLE);
int childIndex = i;
int cWidth = childView.getMeasuredWidth();
int cHeight = childView.getMeasuredHeight();
int centerX = getMeasuredWidth() / 2 - cWidth / 2;
int centerY = (getMeasuredHeight() - 100) - cHeight / 2;
int cl = 0;
int ct = 0;
Double angle = null;
if (childIndex < showMenuBtnNum)
float verticalNum = showMenuBtnNum / 2;
if (showMenuBtnNum % 2 == 0)
// 菜单数量为偶数,中心没有子按钮
verticalNum = verticalNum - 0.5f;
if (childIndex < verticalNum)
//中心线左侧
double currntAngle = (Math.PI / 2 / (verticalNum) * (verticalNum - childIndex));//根据显示数量计算当前所占的角度
angle = currntAngle;
cl = (int) (mRadius * Math.sin(angle));
ct = (int) (mRadius * Math.cos(angle));
cl = centerX - cl;
ct = centerY - ct;
childView.layout(cl, ct, cl + cWidth, ct + cHeight);
else if (childIndex > verticalNum) //中心线右侧
double currentAngle = (Math.PI / 2 / (verticalNum) * (childIndex - verticalNum));
angle = currentAngle;//根据显示数量计算当前所占的角度
cl = (int) (mRadius * Math.sin(angle));
ct = (int) (mRadius * Math.cos(angle));
cl = centerX + cl;
ct = centerY - ct;
childView.layout(cl, ct, cl + cWidth, ct + cHeight);
else
// 菜单数量为奇数,中心有子按钮
if (childIndex < verticalNum)
//中心线左侧
double currntAngle = (Math.PI / 2 / (verticalNum) * (verticalNum - childIndex));//根据显示数量计算当前所占的角度
angle = currntAngle;
cl = (int) (mRadius * Math.sin(angle));
ct = (int) (mRadius * Math.cos(angle));
cl = centerX - cl;
ct = centerY - ct;
childView.layout(cl, ct, cl + cWidth, ct + cHeight);
else if (childIndex == verticalNum) //中心线位置
double currentAngle = 0;
if (verticalNum == 0)
currentAngle = 0;
else
currentAngle = ((Math.PI / 2 / (verticalNum)) * (verticalNum - childIndex));
angle = currentAngle;
cl = (int) (mRadius * Math.sin(angle));
ct = (int) (mRadius * Math.cos(angle));
cl = centerX - cl;
ct = centerY - ct;
childView.layout(cl, ct, cl + cWidth, ct + cHeight);
else if (childIndex > verticalNum && childIndex < showMenuBtnNum) //中心线右侧
double currentAngle = (Math.PI / 2 / (verticalNum) * (childIndex - verticalNum));//根据显示数量计算当前所占的角度
angle = currentAngle;
cl = (int) (mRadius * Math.sin(angle));
ct = (int) (mRadius * Math.cos(angle));
cl = centerX + cl;
ct = centerY - ct;
childView.layout(cl, ct, cl + cWidth, ct + cHeight);
int centrePointX = (int) (getChildAt(0).getX() + getChildAt(0).getWidth() / 2 - childView.getWidth() / 2);
int centrePointY = (int) (getChildAt(0).getY() + getChildAt(0).getHeight() / 2 - childView.getHeight() / 2);
float viewX = centrePointX - cl;
float viewY = centrePointY - ct;
toggleMenuAnim(durationMillis, i, childView, viewX, viewY);
changeMenuStatus();
详细代码见Github,点此传送
欢迎大家star,fork
存在很多不足,望大家见谅
以上是关于安卓自定义半圆弧形菜单的主要内容,如果未能解决你的问题,请参考以下文章