Android Custom View系列《圆形菜单一》
前言
自定义view能够做出很多不同寻常的效果,圆形菜单交互效果不错,目前网上有两个版本,虽然比较庞大,但非常值得研究与学习。
radial-menu-widget: https://code.google.com/p/radial-menu-widget/
Radial-Menu-Widget-Android:https://github.com/strider2023/Radial-Menu-Widget-Android
这两个版本呢实际上第一个是最原始的作者Jason Valestin,后来被Arindam Nath修改后出现了后面的版本。在分析过程中可以逐个击破,关键在于理解要点,本文讲自定义一个圆形的view作为自定义圆形菜单的一个入门基础,暂且命名为CircleView,点击后变化颜色。
源码链接: https://github.com/avenwu/RadialDemo/tree/draw_circle
实现
如果要自定义一个圆形的菜单,那么现有的LinearLayout或者RelativeLayout等都已经无法满足,我们需要从View直接继承,由于需要处理触摸事件,所以需要重载onTouchEvent(),来根据当前触摸的坐标额动作状态调整view
,除此之外需要判断点击的位置出于菜单的可是区域内,在Android中所有的view本质上是矩形区域的,所以需要通过数学计算来判断当前是否点中了菜单,现在我们对这两个关键做类似的实现。
1.初始化画笔菜单位置及大小
在合适的地方初始化资源是很重要的,对画笔和菜单半径等我们可以在构造方法内赋值,

绘制一个圆还需要中心坐标,这个值我们在view的大小确定时初始化,不要尝试直接获取view的高宽,这两个值必须在view绘制后才拿的到,这里我们在onMeasure和onSizeChanged都可以得到view的大小。

2.通过画布绘制菜单
绘制一个圆形比较简单,直接调用canvas的drawCircle方法

3.处理触摸事件
重载onTouchEvent方法我们监听到view上面的触摸动作,一般来说ACTION_DOWN, ACTION_UP, ACTION_MOVE都是比较重要的
我们在点击view的时候更改画笔的颜色为粉红色,当手离开时改回默认的红色,所以可以在ACTION_DOWN时设置color为Color.MAGENTA, 在ACTION_UP时设置为Color.RED
另外在我们按住屏幕后移动位置,这是有可能会移除菜单区域,所以在ACTION_MOVE时我们也需要设置

4.计算触摸位置是否在菜单内
这一步将直接影响我们的触摸效果,这里我们的区域是圆形,所以比较好处理,只需计算触摸点到圆心的距离就可以知道相对位置。

后面当单一圆形菜单分割为多个菜单项时,位置计算会复杂一些。
完整代码:
package com.avenwu.radialdemo; import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View; /**
* @author chaobin
* @date 1/10/14.
*/
public class CircleView extends View {
private float mCenterX;
private float mCenterY;
private float mRadius;
private Paint mPaint; public CircleView(Context context) {
this(context, null);
} public CircleView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
} private void init() {
mRadius = getContext().getResources().getDisplayMetrics().density * 100;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(getContext().getResources().getDisplayMetrics().density * 5);
} @Override
protected void onDraw(Canvas canvas) {
canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec) / 2;
int height = MeasureSpec.getSize(heightMeasureSpec) / 2;
Log.d("CircleView", "onMeasure, height=" + height + ", width=" + width);
updateCenter(width, height);
} @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Log.d("CircleView", "onSizeChanged: w=" + w + ", h=" + h);
updateCenter(w, h);
} void updateCenter(int x, int y) {
mCenterX = x / 2;
mCenterY = y / 2;
} boolean isInside(float x, float y) {
return Math.pow(x - mCenterX, 2) + Math.pow(y - mCenterY, 2)
<= Math.pow(mCenterX - getPaddingLeft(), 2);
} @Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (isInside(event.getX(), event.getY())) {
mPaint.setColor(Color.MAGENTA);
}
break;
case MotionEvent.ACTION_UP:
mPaint.setColor(Color.RED);
break;
case MotionEvent.ACTION_MOVE:
if (!isInside(event.getX(), event.getY())) {
mPaint.setColor(Color.RED);
}
Log.d("CircleView", "position, x=" + event.getX() + ", y=" + event.getY());
break;
}
invalidate();
return true;
} }
Android Custom View系列《圆形菜单一》的更多相关文章
- Android custom View AirConditionerView hacking
package com.example.arc.view; import android.content.Context; import android.graphics.Canvas; import ...
- Android: Custom View和include标签的区别
Custom View, 使用的时候是这样的: <com.example.home.alltest.view.MyCustomView android:id="@+id/customV ...
- android自定义view系列:认识activity结构
标签: android 自定义view activity 开发中虽然我们调用Activity的setContentView(R.layout.activity_main)方法显示View视图,但是vi ...
- android自定义View绘制圆形头像与椭圆头像
要实现这两种效果,需要自定义View,并且有两种实现方式. 第一种: public class BitmapShaders extends View { private BitmapSh ...
- Android 自定义 View 圆形进度条总结
Android 自定义圆形进度条总结 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 微信公众号:牙锅子 源码:CircleProgress 文中如有纰漏,欢迎大家留言指出. 最近 ...
- Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习
作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...
- 简单说说Android自定义view学习推荐的方式
这几天比较受关注,挺开心的,嘿嘿. 这里给大家总结一下学习自定义view的一些技巧. 以后写自定义view可能不会写博客了,但是可以开源的我会把源码丢到github上我的地址:https://git ...
- 手把手带你做一个超炫酷loading成功动画view Android自定义view
写在前面: 本篇可能是手把手自定义view系列最后一篇了,实际上我也是一周前才开始真正接触自定义view,通过这一周的练习,基本上已经熟练自定义view,能够应对一般的view需要,那么就以本篇来结尾 ...
- Android自定义控件View(三)组合控件
不少人应该见过小米手机系统音量控制UI,一个圆形带动画效果的音量加减UI,效果很好看.它是怎么实现的呢?这篇博客来揭开它的神秘面纱.先上效果图 相信很多人都知道Android自定义控件的三种方式,An ...
随机推荐
- Universal USB Installer集开源软件之佳作
有机会下载一份uui的源代码,翻看了一下,呵呵,有意思,几乎是一个开源软件的大杂烩,忽然,恍然大悟,原来,作者才是开源软件精神的代言人,不重复制造轮子的践行者啊. uui网址:https://www. ...
- 88个 Linux 系统管理员必备的监控工具
随着互联网行业的不断发展,各种监控工具多得不可胜数.这里列出网上最全的监控工具.让你可以拥有超过80种方式来管理你的机器.在本文中,我们主要包括以下方面: 命令行工具 网络相关内容 系统相关的监控工具 ...
- 按键精灵与逍遥安卓ADB连接重键方法
1.按键精灵与逍遥安卓ADB连接安装按键精灵与逍遥安卓这两个软件我不用多说了.安装好后把逍遥安卓安装目录下的三个文件adb.exe,AdbWinApi.dll,AdbWinUsbApi.dll 全部复 ...
- (原创)c++11改进我们的模式之改进代理模式,实现通用的AOP框架
c++11 boost技术交流群:296561497,欢迎大家来交流技术. 本次要讲的时候如何改进代理模式,具体来说是动态代理模式,动态代理模式一般实现AOP框架,不懂AOP的童鞋看这里.我前面的博文 ...
- Python 传值和传址 copy/deepcopy
传值:被调函数局部变量改变不会影响主调函数局部变量 传址:被调函数局部变量改变会影响主调函数局部变量 Python参数传递方式:传递对象引用(传值和传址的混合方式),如果是数字,字符串,元组则传值:如 ...
- 在vue-cli生成的项目中使用karma+chrome进行单元测试
用vue-cli生成项目时,如果选择了单元测试,那么会采用karma+mocha作为单元测试框架,默认使用的浏览器是PhantomJs. Karma 是一个基于Node.js的JavaScript测试 ...
- Android.mk用法整理
[时间:2016-05] [状态:Open] 输出消息 由于Android.mk使用的GNU Make的语法,可以方便的使用.ndk提供了一下三种格式的消息输出: error: debug print ...
- mysql关联更新update
https://blog.csdn.net/babyfish13/article/details/78082844 ****************************************** ...
- 【Linux】svn添加用户
1. 找到svn安装路径 /svn/repositories/ (如果不知道,可以搜索 :find / -name svn或者是ps -ef | grep svn) 2.进入该目录的conf,其中包 ...
- hibernate特殊的映射
<property name="update_date" column="update_date" type="java.sql.Timesta ...