参考代码   原文链接:https://blog.csdn.net/qq_29194615/java/article/details/105809980

控件样式:

源代码:RoundMenuView .java

package com.codecandy.views;import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;import com.codecandy.utils.R;import java.util.ArrayList;
import java.util.Date;
import java.util.List;/*** @Description: 圆盘控制台* @Author: liubing* @CreateDate: 2020/05/22 9:06* @UpdateUser: 更新者* @UpdateDate: 2020/05/22 9:06* @UpdateRemark: 更新说明* @Version: 1.0*/
public class RoundMenuView extends View {public final static String PRESS_DOWN="down";public final static String PRESS_UP="up";/*** 变量*/private int coreX;//中心点的坐标Xprivate int coreY;//中心点的坐标Yprivate List<RoundMenu> roundMenus;//菜单列表private boolean isCoreMenu = false;//是否有中心按钮private int coreMenuColor;//中心按钮的默认背景--最好不要透明色private int coreMenuStrokeColor;//中心按钮描边颜色private int coreMenuStrokeSize;//中心按钮描边粗细private int coreMenuSelectColor;//中心按钮选中时的背景颜色private Bitmap coreBitmap;//OK图片private OnClickListener onCoreClickListener;//中心按钮的点击回调private OnMenuViewClickListener onMenuViewClickListener;private float deviationDegree;//偏移角度private int onClickState = -2;//-2是无点击,-1是点击中心圆,其他是点击菜单private int roundRadius;//中心圆的半径private double radiusDistance;//半径的长度比(中心圆半径=大圆半径*radiusDistance)private long touchTime;//按下时间,抬起的时候判定一下,超过300毫秒算点击private boolean mEnableClick = true;private boolean isPermission = false;private int rotate_flag = -1;//正在旋转的方向 -1代表没有旋转  //1左, 2上, 3右, 4下private Toast toast;private String clickEvent;public void setClickEvent(String clickEvent) {this.clickEvent = clickEvent;}public String getClickEvent() {return clickEvent;}public void setPermission(boolean permission) {isPermission = permission;}public boolean ismEnableClick() {return mEnableClick;}public void setmEnableClick(boolean mEnableClick) {this.mEnableClick = mEnableClick;}public void setRotateFlag(int flag) {rotate_flag = flag;invalidate();}public int getRotateFlag() {return rotate_flag;}public RoundMenuView(Context context) {super(context);initView();}public RoundMenuView(Context context, AttributeSet attrs) {super(context, attrs);initView();}public RoundMenuView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);initView();}@Overrideprotected void onDraw(Canvas canvas) {coreX = getWidth() / 2;coreY = getHeight() / 2;roundRadius = (int) (getWidth() / 2 * radiusDistance);//计算中心圆圈半径int padding = dp2px(10f);int paddoutside = dp2px(12f);RectF rect = new RectF(padding, padding, getWidth() - padding, getHeight() - padding);if (roundMenus != null && roundMenus.size() > 0) {float sweepAngle = 360 / roundMenus.size();//每个弧形的角度deviationDegree = sweepAngle / 2;//其实的偏移角度,如果4个扇形的时候是X形状,而非+,设为0试试就知道什么意思了for (int i = 0; i < roundMenus.size(); i++) {RoundMenu roundMenu = roundMenus.get(i);//填充Paint paint = new Paint();paint.setAntiAlias(true);if (onClickState == i) {//选中paint.setColor(roundMenu.selectSolidColor);} else {//未选中paint.setColor(roundMenu.solidColor);}
//               画点击效果canvas.drawArc(rect, deviationDegree + (i * sweepAngle), sweepAngle, true, paint);//画扇形描边paint = new Paint();paint.setAntiAlias(true);paint.setStrokeWidth(roundMenu.strokeSize);paint.setStyle(Paint.Style.STROKE);paint.setColor(roundMenu.strokeColor);canvas.drawArc(rect, deviationDegree + (i * sweepAngle), sweepAngle, roundMenu.useCenter, paint);paint = new Paint();paint.setStrokeWidth(dp2px(1f));paint.setStyle(Paint.Style.STROKE);paint.setColor(Color.parseColor("#03A9F4"));//画大圆canvas.drawArc(rect, 0, 360, false, paint);//画扇形图案Matrix matrix = new Matrix();matrix.postTranslate((float) ((coreX + getWidth() / 2 * roundMenu.iconDistance) - (roundMenu.icon.getWidth() / 2)), coreY - (roundMenu.icon.getHeight() / 2));if (rotate_flag == i) {matrix.postTranslate(-dp2px(10), -dp2px(10));matrix.postRotate(((i + 1) * sweepAngle), coreX, coreY);canvas.drawBitmap(roundMenu.stop_icon, matrix, null);} else {matrix.postRotate(((i + 1) * sweepAngle), coreX, coreY);canvas.drawBitmap(roundMenu.icon, matrix, null);}
//                paint = new Paint();
//                paint.setAntiAlias(true);
//                paint.setStyle(Paint.Style.STROKE);
//                paint.setColor(Color.WHITE);
//                paint.setStrokeWidth(dp2px(2f));
//                canvas.drawArc(rect, 0, 360, false, paint);}}//画中心圆圈if (isCoreMenu) {//填充RectF rect1 = new RectF(coreX - roundRadius, coreY - roundRadius, coreX + roundRadius, coreY + roundRadius);Paint paint = new Paint();paint.setAntiAlias(true);paint.setStrokeWidth(coreMenuStrokeSize);if (onClickState == -1) {paint.setColor(coreMenuSelectColor);} else {paint.setColor(coreMenuColor);}canvas.drawArc(rect1, 0, 360, true, paint);//内圆环
//            paint = new Paint();
//            paint.setAntiAlias(true);
//            paint.setStrokeWidth(dp2px(7));
//            paint.setStyle(Paint.Style.STROKE);
//            paint.setColor(Color.parseColor("#FFFFFF"));
//            canvas.drawArc(rect1, 0, 360, true, paint);//画描边paint = new Paint();paint.setAntiAlias(true);paint.setStrokeWidth(coreMenuStrokeSize);paint.setStyle(Paint.Style.STROKE);paint.setColor(coreMenuStrokeColor);canvas.drawArc(rect1, 0, 360, true, paint);if (coreBitmap != null) {//画中心圆圈的“OK”图标canvas.drawBitmap(coreBitmap, coreX - coreBitmap.getWidth() / 2, coreY - coreBitmap.getHeight() / 2, null);//在 0,0坐标开始画入src}}}public boolean onTouchEvent(MotionEvent event) {OnClickListener onClickListener = null;switch (event.getAction()) {case MotionEvent.ACTION_DOWN:touchTime = new Date().getTime();float textX = event.getX();float textY = event.getY();int distanceLine = (int) getDisForTwoSpot(coreX, coreY, textX, textY);//距离中心点之间的直线距离if (distanceLine <= roundRadius) {//点击的是中心圆;按下点到中心点的距离小于中心园半径,那就是点击中心园了onClickState = -1;onClickListener = onCoreClickListener;} else if (distanceLine <= getWidth() / 2) {//点击的是某个扇形;按下点到中心点的距离大于中心圆半径小于大圆半径,那就是点击某个扇形了float sweepAngle = 360 / roundMenus.size();//每个弧形的角度int angle = getRotationBetweenLines(coreX, coreY, textX, textY);//这个angle的角度是从正Y轴开始,而我们的扇形是从正X轴开始,再加上偏移角度,所以需要计算一下angle = (angle + 360 - 90 - (int) deviationDegree) % 360;onClickState = (int) (angle / sweepAngle);//根据角度得出点击的是那个扇形onClickListener = roundMenus.get(onClickState).onClickListener;} else {//点击了外面onClickState = -2;}if (onClickListener != null) {clickEvent = PRESS_DOWN;onClickListener.onClick(this);}if (rotate_flag == -1 || (rotate_flag != -1 && rotate_flag == onClickState)) {invalidate();}break;case MotionEvent.ACTION_UP:if (onClickState == -1) {onClickListener = onCoreClickListener;} else if (onClickState >= 0 && onClickState < roundMenus.size()) {onClickListener = roundMenus.get(onClickState).onClickListener;}if (onClickListener != null) {clickEvent = PRESS_UP;onClickListener.onClick(this);}onClickState = -2;invalidate();break;}return true;}/*** 添加菜单** @param roundMenu*/public void addRoundMenu(RoundMenu roundMenu) {if (roundMenu == null) {return;}if (roundMenus == null) {roundMenus = new ArrayList<RoundMenu>();}roundMenus.add(roundMenu);invalidate();}/*** 添加中心菜单按钮** @param coreMenuColor* @param coreMenuSelectColor* @param onClickListener*/public void setCoreMenu(int coreMenuColor, int coreMenuSelectColor, int coreMenuStrokeColor,int coreMenuStrokeSize, double radiusDistance, Bitmap bitmap, OnClickListener onClickListener) {isCoreMenu = true;this.coreMenuColor = coreMenuColor;this.coreMenuSelectColor = coreMenuSelectColor;this.coreMenuStrokeColor = coreMenuStrokeColor;this.coreMenuStrokeSize = coreMenuStrokeSize;this.radiusDistance = radiusDistance;coreBitmap = bitmap;this.onCoreClickListener = onClickListener;invalidate();}public void setOnMenuViewClickListener(OnMenuViewClickListener onMenuViewClickListener) {this.onMenuViewClickListener = onMenuViewClickListener;}/*** 获取两条线的夹角** @param centerX* @param centerY* @param xInView* @param yInView* @return*/public static int getRotationBetweenLines(float centerX, float centerY, float xInView, float yInView) {double rotation = 0;double k1 = (double) (centerY - centerY) / (centerX * 2 - centerX);double k2 = (double) (yInView - centerY) / (xInView - centerX);double tmpDegree = Math.atan((Math.abs(k1 - k2)) / (1 + k1 * k2)) / Math.PI * 180;if (xInView > centerX && yInView < centerY) {  //第一象限rotation = 90 - tmpDegree;} else if (xInView > centerX && yInView > centerY) //第二象限{rotation = 90 + tmpDegree;} else if (xInView < centerX && yInView > centerY) { //第三象限rotation = 270 - tmpDegree;} else if (xInView < centerX && yInView < centerY) { //第四象限rotation = 270 + tmpDegree;} else if (xInView == centerX && yInView < centerY) {rotation = 0;} else if (xInView == centerX && yInView > centerY) {rotation = 180;}return (int) rotation;}/*** 求两个点之间的距离** @return*/public static double getDisForTwoSpot(float x1, float y1, float x2, float y2) {float width, height;if (x1 > x2) {width = x1 - x2;} else {width = x2 - x1;}if (y1 > y2) {height = y2 - y1;} else {height = y2 - y1;}return Math.sqrt((width * width) + (height * height));}/*** 扇形的对象类*/public static class RoundMenu {public boolean useCenter = true;//扇形是否画连接中心点的直线public int solidColor = 0x00000000;//背景颜色,默认透明public int selectSolidColor = 0x00000000;//背景颜色,默认透明public int strokeColor = 0xFF03A9F4;//描边颜色,默认透明public int strokeSize = 2;//描边的宽度,默认1public Bitmap icon;//菜单的图片public Bitmap stop_icon;//菜单的图片正在操作public OnClickListener onClickListener;//点击监听public double iconDistance = 0.6;//图标距离中心点的距离}/*** 根据手机的分辨率从 dp 的单位 转成为 px(像素)*/public static int dp2px(float dpValue) {return (int) (0.5f + dpValue * Resources.getSystem().getDisplayMetrics().density);}private void initView() {RoundMenuView.RoundMenu roundMenu = new RoundMenuView.RoundMenu();roundMenu.selectSolidColor = Color.GRAY;
//        roundMenu.icon = drawable2Bitmap(getResources().getDrawable(R.drawable.shape_dian));roundMenu.icon = drawable2Bitmap2(getResources().getDrawable(R.mipmap.ic_arrow_right_blue));roundMenu.stop_icon = drawable2Bitmap2(getResources().getDrawable(R.drawable.ic_blue_dort));roundMenu.onClickListener = new OnClickListener() {@Overridepublic void onClick(View view) {if (onMenuViewClickListener != null)onMenuViewClickListener.OnMenuViewClick(view, clickEvent, 4);}};addRoundMenu(roundMenu);roundMenu = new RoundMenuView.RoundMenu();roundMenu.selectSolidColor = Color.GRAY;roundMenu.icon = drawable2Bitmap2(getResources().getDrawable(R.mipmap.ic_arrow_right_blue));roundMenu.stop_icon = drawable2Bitmap2(getResources().getDrawable(R.drawable.ic_blue_dort));roundMenu.onClickListener = new OnClickListener() {@Overridepublic void onClick(View view) {if (onMenuViewClickListener != null)onMenuViewClickListener.OnMenuViewClick(view, clickEvent, 3);}};addRoundMenu(roundMenu);roundMenu = new RoundMenuView.RoundMenu();roundMenu.selectSolidColor = Color.GRAY;roundMenu.icon = drawable2Bitmap2(getResources().getDrawable(R.mipmap.ic_arrow_right_blue));roundMenu.stop_icon = drawable2Bitmap2(getResources().getDrawable(R.drawable.ic_blue_dort));roundMenu.onClickListener = new OnClickListener() {@Overridepublic void onClick(View view) {if (onMenuViewClickListener != null)onMenuViewClickListener.OnMenuViewClick(view, clickEvent, 2);}};addRoundMenu(roundMenu);roundMenu = new RoundMenuView.RoundMenu();roundMenu.selectSolidColor = Color.GRAY;roundMenu.icon = drawable2Bitmap2(getResources().getDrawable(R.mipmap.ic_arrow_right_blue));roundMenu.stop_icon = drawable2Bitmap2(getResources().getDrawable(R.drawable.ic_blue_dort));roundMenu.onClickListener = new OnClickListener() {@Overridepublic void onClick(View view) {if (onMenuViewClickListener != null)onMenuViewClickListener.OnMenuViewClick(view, clickEvent, 1);}};addRoundMenu(roundMenu);setCoreMenu(Color.parseColor("#FFffff"), Color.parseColor("#FFffff"), Color.parseColor("#3A8EDD"), 2, 0.33, drawable2Bitmap(getResources().getDrawable(R.drawable.shape_trans)), new OnClickListener() {@Overridepublic void onClick(View view) {
//                    Toast.makeText(PreviewActivity.this, "点击了中心圆圈", Toast.LENGTH_SHORT).show();}});}/*** Drawable to bitmap.** @param drawable The drawable.* @return bitmap*/public static Bitmap drawable2Bitmap(final Drawable drawable) {if (drawable instanceof BitmapDrawable) {BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;if (bitmapDrawable.getBitmap() != null) {return bitmapDrawable.getBitmap();}}Bitmap bitmap;if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {bitmap = Bitmap.createBitmap(1, 1,drawable.getOpacity() != PixelFormat.OPAQUE? Bitmap.Config.ARGB_8888: Bitmap.Config.RGB_565);} else {bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight(),drawable.getOpacity() != PixelFormat.OPAQUE? Bitmap.Config.ARGB_8888: Bitmap.Config.RGB_565);}Canvas canvas = new Canvas(bitmap);drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());drawable.draw(canvas);return bitmap;}/*** Drawable to bitmap.** @param drawable The drawable.* @return bitmap*/private static Bitmap drawable2Bitmap2(final Drawable drawable) {Bitmap bitmap;bitmap = Bitmap.createBitmap(dp2px(25),dp2px(25),drawable.getOpacity() != PixelFormat.OPAQUE? Bitmap.Config.ARGB_8888: Bitmap.Config.RGB_565);Canvas canvas = new Canvas(bitmap);drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());drawable.draw(canvas);return bitmap;}/*** Interface definition for a callback to be invoked when a view is clicked.*/public interface OnMenuViewClickListener {/*** Called when a view has been clicked.** @param v The view that was clicked.*/void OnMenuViewClick(View v, String event, int position);}}

ic_blue_dort.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="oval"><sizeandroid:width="20dp"android:height="20dp" /><solid android:color="#3A8EDD" />
</shape>

shape_trans.xml:

<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="oval"><sizeandroid:width="6dp"android:height="6dp" /><solid android:color="@color/transparent" />
</shape>
ic_arrow_right_blue:随便一个图片或是资源图片。图中的方向键头。

android 方向控件 MenuView 上下左右,东南西北相关推荐

  1. Android UI控件和布局

    说明: 本文是郭霖<第一行代码-第3版>的读书笔记 4.1 如何编写程序界面 编写XML,这是传统的方法 ConstraintLayout,Google推出的新方法,可以在可视化编辑器中拖 ...

  2. Android 开源控件与常用开发框架开发工具类

    Android的加载动画AVLoadingIndicatorView 项目地址: https://github.com/81813780/AVLoadingIndicatorView 首先,在 bui ...

  3. 详细Android studio 控件对齐方式

    控件对齐方式 请移步:常用的控件设置 格式大全 记忆方法 根据命名规则可以很轻松地理解并记忆每个格式的作用: gravity: 重力; above : 在--上面; Bottom : 底部:末端: a ...

  4. 一个Demo让你掌握Android所有控件

    一个Demo让你掌握Android所有控件 原文:一个Demo让你掌握Android所有控件 本文是转载收藏,侵删,出处:"安卓巴士"      下面给出实现各个组件的源代码: 1 ...

  5. Android提供了哪些主要UI控件,Android必备:Android UI控件的了解与学习

    因为工做须要,最近一段时间,须要进行Android App开发的学习,以前简单的进行过Android的了解,对于基本的Android环境的搭建等已经有过整理,一个Android App是由一个或多个A ...

  6. android相对控件居中对齐,相对布局(RelativeLayout)常用属性

    RelativeLayout子控件的一些属性: //相对于同级控件对齐方式 android:layout_alignBaseline     将该控件的baseline与给定ID的baseline对齐 ...

  7. Android开源控件收集整理

    一 .基本控件 TextView HTextView 一款支持TextView文字动画效果的Android组件库.GitHub - hanks-zyh/HTextView: Animation eff ...

  8. Android 原生控件之一 TextView

    Android 原生控件之一 TextView 前言 来源 开始 XML属性 1.android:allowUndo 2.android:autoLink 3.android:autoSizeMaxT ...

  9. Android开源控件ViewPager Indicator的使用方法

     1月16日厦门 OSC 源创会火热报名中,奖品多多哦   摘要 Android开源控件ViewPager Indicator的使用介绍 ViewPagerIndicator 目录[-] 1. V ...

最新文章

  1. 使用 Python 在 GitHub 上运行你的博客
  2. linux系统正常停机的命令,Linux系统重启命令大全
  3. Nacos的服务注册表结构是怎样的?
  4. B 站面试官:“啥是重定向?”
  5. java环境怎样搭建_如何学习JAVA?怎么搭建JAVA环境?怎么安装JDK?
  6. 如何解决IE6的3像素问题?
  7. 联邦学习在视觉领域的应用,揭秘AI人工智能创新应用奖获奖案例
  8. VC++ 6.0如何创建与调用动态链接库
  9. 单机dnf正在连接服务器,dnf提示正在连接服务器解决方案
  10. tf 设置多显卡_海美迪H7四代解码4k hdr局域网教程,用TF卡双启动libreELEC成功
  11. codeIgniter 4升级使用
  12. 怎么把win10右下角的隐藏图标调出来(把倒三角调出来)
  13. Django实现adminx后台网站访问的IP记录统计
  14. Python collections模块之Counter()详解
  15. CITA环境搭建与运行
  16. 制造业工厂需要关注的工业物联网解决方案
  17. DFT的简单介绍(上)
  18. php英文文献翻译,php外文文献翻译_英语论文
  19. python中对象的特性_python面对对象-三大特性
  20. 如何使用Inkscape软件绘制一个LOGO

热门文章

  1. SSL 证书购买以及Nginx配置相关问题
  2. linux 编辑文件 cat 跳到指定行,Linux基础命令(二)
  3. 使用Excel 表示汽车、摩托车10年免检时间、非常清晰。
  4. (1.2)bark-ml
  5. YC全球总裁:我招揽陆奇好多年,如今终于如愿了!
  6. 武汉云数时代网络科技有限公司网店代运营托管优势?
  7. fsl左右海马体分割+freesurfer合并
  8. JavaScript 静态方法
  9. 阿里Java学习路线:阶段 1:Java语言基础-Java面向对象编程:第30章:链表的定义与使用:课时145:综合实战:超市购物车(含完整代码)
  10. 个人公众号,以后文章会在公众号首发