安卓自定义半圆弧形菜单

xiaoxiao2021-02-28  66

安卓开发自定义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

存在很多不足,望大家见谅

转载请注明原文地址: https://www.6miu.com/read-96958.html

最新回复(0)