/*** 仿遥控器上下左右ok圆形菜单* Created by*/public class RoundMenuView extends View {/*** 变量*/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 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(7f));paint.setStyle(Paint.Style.STROKE);paint.setColor(Color.parseColor("#3B3C41"));//画大圆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 = "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 = "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();}/*** 获取两条线的夹角** @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 = 0xFFBFC0C2;//描边颜色,默认透明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.stop_icon = drawable2Bitmap2(getResources().getDrawable(R.drawable.icon_stop));roundMenu.onClickListener = new OnClickListener() {@Overridepublic void onClick(View view) {}};addRoundMenu(roundMenu);roundMenu = new RoundMenuView.RoundMenu();roundMenu.selectSolidColor = Color.GRAY;roundMenu.icon = drawable2Bitmap(getResources().getDrawable(R.drawable.shape_dian));roundMenu.stop_icon = drawable2Bitmap2(getResources().getDrawable(R.drawable.icon_stop));roundMenu.onClickListener = new OnClickListener() {@Overridepublic void onClick(View view) {}};addRoundMenu(roundMenu);roundMenu = new RoundMenuView.RoundMenu();roundMenu.selectSolidColor = Color.GRAY;roundMenu.icon = drawable2Bitmap(getResources().getDrawable(R.drawable.shape_dian));roundMenu.stop_icon = drawable2Bitmap2(getResources().getDrawable(R.drawable.icon_stop));roundMenu.onClickListener = new OnClickListener() {@Overridepublic void onClick(View view) {}};addRoundMenu(roundMenu);roundMenu = new RoundMenuView.RoundMenu();roundMenu.selectSolidColor = Color.GRAY;roundMenu.icon = drawable2Bitmap(getResources().getDrawable(R.drawable.shape_dian));roundMenu.stop_icon = drawable2Bitmap2(getResources().getDrawable(R.drawable.icon_stop));roundMenu.onClickListener = new OnClickListener() {@Overridepublic void onClick(View view) {}};addRoundMenu(roundMenu);setCoreMenu(Color.parseColor("#FFFFFFFF"), Color.parseColor("#FFFFFFFF"), Color.parseColor("#FFBFC0C2"),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*/private 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;}}

shape_dian.xml如下

<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="oval"><sizeandroid:width="6dp"android:height="6dp" /><solid android:color="@color/black" />
</shape>
icon_stop是一张图片

效果图

Android 自定义圆盘,方向盘相关推荐

  1. android自定义圆盘时钟

    自定义圆盘时钟的大概流程:因为圆盘时钟的圆盘是不需要动的,所以不必要加在自定义的view里面,在view里面只需要绘制秒针和分针时针并控其转动即可. 以下就是自定义view的主要代码: package ...

  2. 短视频系统源代码,自定义圆盘,方向盘

    短视频系统源代码中,自定义圆盘,方向盘相关代码: /*** 仿遥控器上下左右ok圆形菜单* Created by*/public class RoundMenuView extends View {/ ...

  3. Android自定义半圆形圆盘滚动选择器View

    本文为原创作品,转载请注明出处:https://blog.csdn.net/wjj1996825/article/details/80646526 前段时间公司项目要求做一个特效的滑动选择器,效果如下 ...

  4. Android自定义ViewGroup基本步骤

    1.自定义属性,获取自定义属性,可参考 ​ Android自定义View基本步骤 ​ 2.onMeasure() 方法,for循环测量子View,根据子View的宽高来计算自己的宽 高 3.onDra ...

  5. Android自定义View —— TypedArray

    在上一篇中Android 自定义View Canvas -- Bitmap写到了TypedArray 这个属性 下面也简单的说一下TypedArray的使用 TypedArray 的作用: 用于从该结 ...

  6. Android 自定义View —— Canvas

    上一篇在android 自定义view Paint 里面 说了几种常见的Point 属性 绘制图形的时候下面总有一个canvas ,Canvas 是是画布 上面可以绘制点,线,正方形,圆,等等,需要和 ...

  7. android 自定义loading,Android自定义动画-StarLoadingView

    今天来分享第二个自定义loading的动画,起了个名字叫 蹦跶的星星 ,还是老规矩先介绍,后上图. 实现效果在最后,GIF有点大,手机流量慎重. 介绍 首先声明做这个动画的初衷是为了学习和分享,所以从 ...

  8. android自定义view获取控件,android 自定义控件View在Activity中使用findByViewId得到结果为null...

    转载:http://blog.csdn.net/xiabing082/article/details/48781489 1.  大家常常自定义view,,然后在xml 中添加该view 组件..如果在 ...

  9. android 自定义命名空间,Android自定义ActionBar实例

    本文实例讲述了android自定义actionbar的实现方法.分享给大家供大家参考.具体实现方法如下: android 3.0及以上已经有了actionbar的api,可以通过引入support p ...

最新文章

  1. mbstowcs 和 wcstombs函数:C语言提供的宽字符和多字节字符转换函数
  2. 线段树(结构体建法_QAQ)
  3. 百度开源 FAQ 问答系统(AnyQ)安装---Linux(无docker)+小白编译AnyQ-dockerlinux[CentOs]
  4. 我的个人中心前端开发源代码_个人博客
  5. spring结合ehcache-spring-annotations配置缓存
  6. 跟着李开复去硅谷,你有疑惑我帮问 | 互动一则
  7. Linux忘记root密码
  8. hibernate框架学习笔记2:配置文件详解
  9. 系统架构师学习笔记_第十一章(下)_连载
  10. java应用中如何连接dbproxy_GitHub - alchemystar/hero: 用c语言写的dbproxy
  11. 在线编辑fckeditor3
  12. 简单有限元分析技术(详细步骤讲解)
  13. 计算机程序员 面试题库,计算机软考程序员面试题精选题2
  14. iPad除了用来吃喝玩乐,还能能写代码了?
  15. 换成Everyone还是访问被拒绝的解决办法
  16. 辣条君写爬虫4【帮小姐姐删垃圾邮件】
  17. c# NPOI 导出Excel 冻结窗格
  18. 编译原理学习之:上下文无关文法(Context-free Grammar)和下推自动机(Push-down automata)
  19. 对于position定位的认识
  20. 英语天天秀(2007/06/16) -- 老美口头禅

热门文章

  1. 吴恩达深度学习L2W1——神经网络权重初始化方法、正则化
  2. Uni.me免费域名申请注册和使用教程
  3. t440 linux指纹识别,ThinkPad X220 Ubuntu 14.10 上安装指纹识别
  4. 计算机软考 零基础,零基础计算机软考攻略
  5. python openpyxl三行代码将列表数据依次加入excel单元格并生成图表
  6. 我和滴滴打车司机的那些事
  7. 大坝安全监测系统:水库“守坝人”!
  8. 海量日志存储和查询方法及系统
  9. 小程序毕设作品之微信美食菜谱小程序毕业设计成品(2)小程序功能
  10. 脑波艺术 · 脑机、数字疗法、人工智能与看不见的“病人”