我的视频课程:《FFmpeg打造Android万能音频播放器》

最近帮朋友做了一个动画菜单,感觉有一定的实用价值,就在此给大家分享一下,先看看效果:源码下载地址在末尾

实现思路:

从图中可以看出,这三个(或更多,需要自己再实现)菜单是围绕着中心点旋转的,旋转分为2层,背景旋转和菜单旋转,背景旋转可以直接用旋转动画来实现;菜单的旋转是在以中心点为圆心的圆环上,所以这里用了根据旋转角度求此点在直角坐标系中的坐标点的函数(x = r * cos(rotation* 3.14 / 180) 和y = r * sin(rotation* 3.14 / 180) ),然后根据获取到的点的位置来设置菜单的位置就能实现这种效果。由此可见 数学是很重要的 哈哈~~

有了思路我们就能用代码来实现了:

1、首先自定义View继承相对布局并重写构造函数

/*** Created by ywl on 2016/8/7.*/
public class CircleMenuLayout extends RelativeLayout {public CircleMenuLayout(Context context) {this(context, null);}public CircleMenuLayout(Context context, AttributeSet attrs) {this(context, attrs, 0);}/*** 初始化布局 把旋转背景和中心点添加进去* @param context* @param attrs* @param defStyleAttr*/public CircleMenuLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);this.context = context;layoutInflater = LayoutInflater.from(context);menuitems = new ArrayList<View>();centerview = new View(context);//中心点centerview.setId(ID_CENTER_VIEW);LayoutParams lp = new LayoutParams(0, 0);lp.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);addView(centerview, lp); //添加中心的 用于旋转定位progressBar = new ProgressBar(context);//旋转的背景LayoutParams lp2 = new LayoutParams(dip2px(context, 90), dip2px(context, 90));lp2.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);addView(progressBar, lp2);progressBar.setIndeterminateDrawable(context.getResources().getDrawable(R.mipmap.icon_circle_menu));}
}

构造函数中添加中心定位点和旋转背景图片,并设置合适的大小。

2、根据传入的图片数组和菜单名字数组,生成菜单原始位置效果。

/*** 菜单的数量 和 半径 名字 和图片 这里只为3个菜单做了适配* @param size* @param center_distance*/public void initMenuItem(int size, int center_distance, String[] titles, int[] imgs){radus = 360f / size;int width = dip2px(context, 50); //菜单宽度int height = dip2px(context, 50);//菜单高度for(int i = 0; i < size; i++) //循环添加布局{int top = 0;int left = 0;top = -(int)(Math.sin(radus * i * 3.1415f / 180) * center_distance); //r   *   cos(ao   *   3.14   /180   )left = -(int)(Math.cos(radus * i * 3.1415f / 180) * center_distance); //计算位置点LayoutParams lp = new LayoutParams(dip2px(context, 50), dip2px(context, 50));View view = layoutInflater.inflate(R.layout.item_circle_menu, this, false);view.setTag(i);TextView tvname = (TextView) view.findViewById(R.id.tv_name);ImageView ivimg = (ImageView) view.findViewById(R.id.img);tvname.setText(titles[i]);ivimg.setImageResource(imgs[i]);view.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {//根据点击的区域 旋转菜单if(!isrun) {tag = (int) v.getTag();currentPosition = tag;if(tag == 0){finishdus = -360;}else if(tag == 1){finishdus = -120;}else if(tag == 2){finishdus = -240;}LayoutParams lp = (LayoutParams) v.getLayoutParams();int l = lp.leftMargin;int t = lp.topMargin;if (t > -dip2px(context, 5) && l > -dip2px(context, 5)) {oldradus = 120f;isright = false;} else if (t >  -dip2px(context, 5) && l <  -dip2px(context, 5)) {oldradus = 120f;isright = true;} else if (t <  -dip2px(context, 5)) {oldradus = 0f;}sub = 0;circleMenu(8, dip2px(context, 45), oldradus, isright);}}});lp.addRule(RelativeLayout.BELOW, centerview.getId());lp.addRule(RelativeLayout.RIGHT_OF, centerview.getId());lp.setMargins(-width / 2 + top, -height / 2 + left, 0, 0);addView(view, lp);menuitems.add(view);}handler.postDelayed(runnable, 0);}

根据菜单的数量循环计算每个菜单的位置,然后在相应的位置添加相应的菜单就可以实现菜单的初始化了。这里为每个菜单添加了点击事件,但是只适配了3个菜单的情况,至于其他数量的菜单,可以自己来改或者写一个通用的方法来计算点击位置。

3、背景旋转动画:

 /*** 根据度数来旋转菜单 菜单中心都在一个圆上面 采用圆周运动来旋转* @param offserradius* @param center_distance* @param d* @param right*/public void circleMenu(float offserradius, int center_distance, float d, boolean right){if(oldradus != 0){progressBar.clearAnimation();if(isright){mRotateUpAnim = new RotateAnimation(bgdus, bgdus + 120,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);bgdus += 120;}else{mRotateUpAnim = new RotateAnimation(bgdus, bgdus - 120,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);bgdus -= 120;}lir = new LinearInterpolator();mRotateUpAnim.setDuration(350);mRotateUpAnim.setFillAfter(true);mRotateUpAnim.setInterpolator(lir);//        mRotateUpAnim.setRepeatCount(Animation.INFINITE);progressBar.startAnimation(mRotateUpAnim);}circleMenuItem(offserradius, center_distance, d, right);}

这个比较简单,就是根据旋转的角度,启用旋转动画。

4、旋转菜单:

/*** 菜单旋转* @param offserradius* @param center_distance* @param d* @param right*/public void circleMenuItem(float offserradius, int center_distance, float d, boolean right){sub += offserradius;if(sub > d){if(onMenuItemSelectedListener != null){onMenuItemSelectedListener.onMenuItemOnclick(tag);}isrun = false;return;}if(right) {offsetradus -= offserradius;}else{offsetradus += offserradius;}int size = menuitems.size();int width = dip2px(context, 50);int height = dip2px(context, 50);for(int i = 0; i < size; i++){if(Math.abs(sub - d) <= 8){offsetradus = finishdus;}LayoutParams lp = (LayoutParams) menuitems.get(i).getLayoutParams();float ds = radus * i + offsetradus;int top = -(int)(Math.sin(ds * 3.1415f / 180) * center_distance); //r   *   cos(ao   *   3.14   /180   )int left = -(int)(Math.cos(ds * 3.1415f / 180) * center_distance);lp.setMargins(-width / 2 + top, -height / 2 + left, 0, 0);menuitems.get(i).requestLayout();}if(sub <= d) {isrun = true;offsetradus = offsetradus % 360;handler.postDelayed(runnable, 5);}else{if(onMenuItemSelectedListener != null){onMenuItemSelectedListener.onMenuItemOnclick(tag);}isrun = false;}}

这里旋转是根据初始化时每个菜单所在的位置来求的旋转角度,然后启动handler来动递加或递减角度来求响应的位置,就实现了动画效果。

5、手动设置菜单项(有局限,没有通用性):

/*** 设置旋转到哪个菜单项* @param tag*/public void setCurrentTag(int tag){if(currentPosition == tag){return;}if(tag == 0){finishdus = -360;}else if(tag == 1){finishdus = -120;}else if(tag == 2){finishdus = -240;}if(currentPosition == 0) //当前是0{if(tag == 1){oldradus = 120f;isright = true;}else if(tag == 2){oldradus = 120f;isright = false;}}else if(currentPosition == 1){if(tag == 2){oldradus = 120f;isright = true;}else if(tag == 0){oldradus = 120f;isright = false;}}else if(currentPosition == 2){if(tag == 0){oldradus = 120f;isright = true;}else if(tag == 1){oldradus = 120f;isright = false;}}currentPosition = tag;this.tag = tag;sub = 0;circleMenu(8, dip2px(context, 45), oldradus, isright);}

这样就可以实现旋转效果了。

6、调用方法:

(1)布局文件:

<com.ywl5320.circlemenu.CircleMenuLayoutandroid:id="@+id/cml_menu"android:layout_width="150dp"android:layout_height="150dp"android:layout_centerHorizontal="true"android:layout_alignParentBottom="true"android:layout_marginBottom="92dp"/>

(2)菜单布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="100dp"android:layout_height="100dp"android:padding="5dp"android:gravity="center"><ImageViewandroid:id="@+id/img"android:layout_width="25dp"android:layout_height="25dp"android:scaleType="fitXY"/><TextViewandroid:id="@+id/tv_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="菜单项"android:textSize="9sp"android:gravity="center"android:textColor="#ffffff"/>
</LinearLayout>

(3)Activity中调用

<span style="white-space:pre">  </span>cmlmenu = (CircleMenuLayout) findViewById(R.id.cml_menu);btn = (Button) findViewById(R.id.btn);cmlmenu.initDatas(titles, imgs);cmlmenu.setOnMenuItemSelectedListener(new CircleMenuLayout.OnMenuItemSelectedListener() {@Overridepublic void onMenuItemOnclick(int code) {if(code == 0)//{Toast.makeText(MainActivity.this, "支付宝", Toast.LENGTH_SHORT).show();}else if(code == 1){Toast.makeText(MainActivity.this, "银联", Toast.LENGTH_SHORT).show();}else if(code == 2){Toast.makeText(MainActivity.this, "微信", Toast.LENGTH_SHORT).show();}}});

OK,就完成了三个菜单旋转效果(注:这里仅仅是为了3个菜单而设计的,其他个数的自己还需要精简或更改一些代码,相信自己改出来的会更有收获的~~)。

Github:CircleMenu

CSDN:CircleMenu

欢迎下载和Star

Android 圆形旋转菜单相关推荐

  1. android圆形旋转菜单,而对于移动转换功能支持

    LZ该公司最近接手一个项目,需要写一个圆形旋转菜单,和菜单之间的移动换位支持,我本来以为这样的demo如若互联网是非常.想想你妈妈也帮不了我,空旋转,但它不能改变位置,所以LZ我们只能靠自己摸索. 最 ...

  2. android圆形菜单,android 圆形旋转菜单例子

    [实例简介] [实例截图] [核心代码] package com.szugyi.circlemenu.view; /* * Copyright 2013 Csaba Szugyiczki * * Li ...

  3. android 双层旋转菜单,Android 高仿【优酷】圆盘旋转菜单的实现

    目前,用户对安卓应用程序的UI设计要求越来越高,因此,掌握一些新颖的设计很有必要. 比如菜单,传统的菜单已经不能满足用户的需求. 其中优酷中圆盘旋转菜单的实现就比较优秀,这里我提供下我的思路及实现,仅 ...

  4. ios 圆形旋转菜单_iOS 圆环菜单

    前言 之前的一个项目,没有使用TabBar,而是选择用圆环作为用户点击的菜单,加上深蓝的冷色调,APP看着还蛮高大上,先看下效果图: demo.gif 效果图分析 1.类似地球的是一张Image,其余 ...

  5. ios 圆形旋转菜单_iOS高级动画:圆形树展开收起动画

    转自:标哥的技术博客,作者:黄仪标(微博) 前段时间帮某某做了一个动画效果,今天分享给大家.关于动画的基础知识,这里不会细说,如果您还没有核心动画的基础知识,请先阅读相关文章,了解核心动画如何使用,然 ...

  6. html转动的圆圈,CSS圆形旋转效果 纯CSS制作圆形旋转菜单效果(七步完成)

    我们理念中的菜单都是矩形的,不是横向排列就是纵向排列,这里我们打破了常规的思维,把菜单做成圆形的. 在这里我们不得不克服几个问题: 如何定义html如何悬停定位菜单元素 在此之前先看一下最终效果是怎样 ...

  7. android圆形贝塞尔 菜单,Android 贝塞尔曲线——圆渐变心

    大家好!我是一名执着的Android开发攻城狮,第一次写简书,没有写好的希望大家多多包涵,万事开头难,从去年开始我就想写点自己的东西,但是一直没有写下去的勇气和毅力,希望这是我一个好的习惯开始.在这我 ...

  8. ios 圆形旋转菜单_iOS实现滑动弧形菜单的思路与方法

    前言 最近公司的项目中需要用到弧形菜单,起初自定义UICollectionView的layout,但实现出的效果并不符合项目中要求按钮始终垂直于界面.界面始终保持几个按钮等一系列需求(是我水平不够), ...

  9. ios 圆形旋转菜单_iOS 屏幕强制旋转 (模态、Push、导航栏、状态栏)

    界面旋转准备 在AppDelegate.h中添加属性 //是否旋转 @property (nonatomic, assign) BOOL isRotation; 在AppDelegate.m中添加方法 ...

最新文章

  1. 浏览器缓存网站静态文件
  2. How to reduce Index size on disk?减少ES索引大小的一些小手段
  3. linux shell 基础 使用日志与心得
  4. HeadFirst设计模式(四) - 工厂模式之1 - 简单工厂
  5. PAT练习之字符串处理
  6. 2-2 人工智能的前景|人工智能框架TensorFlow应用实践笔记
  7. H5 C3中的概念(一)
  8. 【渝粤教育】电大中专药剂学基础知识 (3)作业 题库
  9. c语言bfs程序讲解,面试算法--二叉树DFS/BFS实现(C语言)
  10. LeetCode MySQL 1264. 页面推荐(union)
  11. unity3d双面材质_[转]unity3d中创建双面材质
  12. 多种负载均衡算法及其Java代码实现
  13. Excel表中的数据导入到数据库中
  14. 有道词典在谷歌Chrome浏览器中无法取词的解决方法
  15. 弱电工程施工组织设计
  16. 稳压二极管限流电阻怎么选择
  17. SVM——支持向量回归(SVR)
  18. RFC1180 TCP/IP指南
  19. 退出android recovery界面,怎么退出recovery模式?
  20. 计算理财产品收益的JS代码

热门文章

  1. 微信小程序 请求数据
  2. MFC颜色调配 | vc++6.0颜色设置,如何修改控件颜色
  3. autocad不能画图_说说基本的画图软件—AutoCAD(一)
  4. Ue4 UI优化文档整理理解
  5. 大数据案例--网站流量项目(上)
  6. ctfshow摆烂杯
  7. java cron 每100分钟执行一次
  8. 【C语言】编程计算第几天气球才能被吹爆
  9. 刚入门学3D游戏美术设计最常见的几个问题
  10. 绕线机算法模型(Simulink仿真验证+PLC代码实现)