在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); }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
存在很多不足,望大家见谅
