
最近帮朋友做了一个动画菜单,感觉有一定的实用价值,就在此给大家分享一下,先看看效果:
实现思路:
从图中可以看出,这三个(或更多,需要自己再实现)菜单是围绕着中心点旋转的,旋转分为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,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),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() { @OverrIDe public 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,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); 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,float d,boolean right) { if(oldradus != 0) { progressbar.clearanimation(); if(isright) { mRotateUpAnim = new RotateAnimation(bgdus,bgdus + 120,Animation.relative_TO_SELF,0.5f,0.5f); bgdus += 120; } else { mRotateUpAnim = new RotateAnimation(bgdus,bgdus - 120,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,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,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,isright); } 这样就可以实现旋转效果了。
6、调用方法:
(1)布局文件:
<com.ywl5320.circlemenu.CircleMenulayout androID: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"> <ImageVIEw androID:ID="@+ID/img" androID:layout_wIDth="25dp" androID:layout_height="25dp" androID:scaleType="fitXY"/> <TextVIEw androID: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 > </span>cmlmenu = (CircleMenulayout) findVIEwByID(R.ID.cml_menu); btn = (button) findVIEwByID(R.ID.btn); cmlmenu.initDatas(Titles,imgs); cmlmenu.setonMenuItemSelectedListener(new CircleMenulayout.OnMenuItemSelectedListener() { @OverrIDe public 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个菜单而设计的,其他个数的自己还需要精简或更改一些代码,相信自己改出来的会更有收获的~~)。
以上所述是小编给大家介绍的AndroID圆形旋转菜单开发实例,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!
总结以上是内存溢出为你收集整理的Android圆形旋转菜单开发实例全部内容,希望文章能够帮你解决Android圆形旋转菜单开发实例所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)