前言

自定义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系列《圆形菜单一》的更多相关文章

  1. Android custom View AirConditionerView hacking

    package com.example.arc.view; import android.content.Context; import android.graphics.Canvas; import ...

  2. Android: Custom View和include标签的区别

    Custom View, 使用的时候是这样的: <com.example.home.alltest.view.MyCustomView android:id="@+id/customV ...

  3. android自定义view系列:认识activity结构

    标签: android 自定义view activity 开发中虽然我们调用Activity的setContentView(R.layout.activity_main)方法显示View视图,但是vi ...

  4. android自定义View绘制圆形头像与椭圆头像

    要实现这两种效果,需要自定义View,并且有两种实现方式.   第一种: public class BitmapShaders extends View {     private  BitmapSh ...

  5. Android 自定义 View 圆形进度条总结

    Android 自定义圆形进度条总结 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 微信公众号:牙锅子 源码:CircleProgress 文中如有纰漏,欢迎大家留言指出. 最近 ...

  6. Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...

  7. 简单说说Android自定义view学习推荐的方式

    这几天比较受关注,挺开心的,嘿嘿. 这里给大家总结一下学习自定义view的一些技巧.  以后写自定义view可能不会写博客了,但是可以开源的我会把源码丢到github上我的地址:https://git ...

  8. 手把手带你做一个超炫酷loading成功动画view Android自定义view

    写在前面: 本篇可能是手把手自定义view系列最后一篇了,实际上我也是一周前才开始真正接触自定义view,通过这一周的练习,基本上已经熟练自定义view,能够应对一般的view需要,那么就以本篇来结尾 ...

  9. Android自定义控件View(三)组合控件

    不少人应该见过小米手机系统音量控制UI,一个圆形带动画效果的音量加减UI,效果很好看.它是怎么实现的呢?这篇博客来揭开它的神秘面纱.先上效果图 相信很多人都知道Android自定义控件的三种方式,An ...

随机推荐

  1. Atitit opencv 模板匹配

    Atitit opencv 模板匹配 1.1. 图片1 1.2. Atitit opencv 模板匹配  6中匹配算法貌似效果区别不大1 1.3. 对模板缩放的影响 一般的缩放可以,太大了就歇菜了.. ...

  2. error occurred during the file system check

    fsck -c 然后一路:y reboot 问题解决!!!

  3. python-zip方法

    zip 返回一个将多个可迭代对象组合成一个元组序列的迭代器. 1.  循环多个list的数据: letters = ['a', 'b', 'c'] nums = [1, 2, 3] for lette ...

  4. [CoreOS 转载]CoreOS实践指南(二):架设CoreOS集群

    转载:http://www.csdn.net/article/2015-01-04/2823399 摘要:CoreOS是一个采用了高度精简的系统内核及外围定制的操作系统.ThoughtWorks的软件 ...

  5. [iOS Xcode8报错]dyld: Library not loaded: /System/Library/Frameworks/UserNotifications.framework/UserN

    [iOS Xcode8报错]dyld: Library not loaded: /System/Library/Frameworks/UserNotifications.framework/UserN ...

  6. 【转】Linux mysql停止失败的解决办法 Stopping MySQL database server mysqld [fail]

    root@ubuntu:/# /etc/init.d/mysql stop * Stopping MySQL database server mysqld [fail] root@ubuntu:/# ...

  7. Mysql查看连接数相关信息

    MySQL查看连接数相关信息在 数据库:INFORMATION_SCHEMA 表:PROCESSLIST 表结构如下: mysql> desc PROCESSLIST; +---------+- ...

  8. 【转】一件有趣的事:我用 Python 爬了爬自己的微信朋友

    偶然了解到 Python 里的 itchat 包,它已经完成了 wechat 的个人账号 API 接口,使爬取个人微信信息更加方便. 于是乎玩心一起,打算爬一下自己的微信. 步骤核心: 网页启动not ...

  9. error LNK2005: _DllMain@12 已经在 MSVCRTD.lib(dllmain.obj) 中定义

    备注:我上次遇到这个问题是Win32 DLL项目中无意中include了afxwin.h,这个是MFC的头文件,把这个include删掉就解决了 ================ 转自:http:// ...

  10. Excel中功能清单转Project任务

    接:http://www.cnblogs.com/vipsoft/p/8495220.html 1.在E列输入公式: =IF(LEN(A2)>1,1,IF(LEN(B2)>1,2,IF(L ...