Android自定义控件之仿优酷菜单
去年的优酷hd版有过这样一种菜单,如下图:
应用打开之后,先是三个弧形的三级菜单,点击实体键menu之后,这三个菜单依次旋转退出,再点击实体键menu之后,一级菜单会旋转进入,点击一级菜单,二级菜单旋转进入,点击二级菜单的menu键,三级菜单旋转进入,再次点击二级菜单的旋转键,三级菜单又会旋转退出,这时再点击一级菜单,二级菜单退出,最后点击实体menu键,一级菜单退出。
总体来说实现这样的功能:
(1)点击实体menu键时,如果界面上有菜单显示,不管有几个,全部依次退出,如果界面上没有菜单显示,则显示一级菜单。
(2)点击一级菜单的home键时,如果此时界面只有一级菜单,则显示二级菜单,否则让除了一级菜单外的菜单全都依次退出。
(3)点击二级菜单的menu键时,如果三级菜单已经显示,则让它旋转退出,如果三级菜单未显示则让它旋转进入。
好了,今天我们主要实现上述效果。
先来看布局文件
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.customwidget.mainactivity" > <relativelayout android:id="@+id/menu_level1" android:layout_width="100dp" android:layout_height="50dp" android:layout_alignparentbottom="true" android:layout_centerhorizontal="true" android:background="@drawable/level1" > <imagebutton android:id="@+id/level1_home" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerinparent="true" android:layout_marginbottom="10dp" android:background="@drawable/icon_home" android:onclick="myclick" /> </relativelayout> <relativelayout android:id="@+id/menu_level2" android:layout_width="200dp" android:layout_height="100dp" android:layout_alignparentbottom="true" android:layout_centerhorizontal="true" android:background="@drawable/level2" > <imagebutton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentbottom="true" android:layout_marginbottom="10dp" android:layout_marginleft="15dp" android:background="@drawable/icon_search" /> <imagebutton android:id="@+id/level2_menu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerhorizontal="true" android:layout_margintop="7dp" android:background="@drawable/icon_menu" android:onclick="myclick" /> <imagebutton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentbottom="true" android:layout_alignparentright="true" android:layout_marginbottom="10dp" android:layout_marginright="15dp" android:background="@drawable/icon_myyouku" /> </relativelayout> <relativelayout android:id="@+id/menu_level3" android:layout_width="320dp" android:layout_height="162dp" android:layout_alignparentbottom="true" android:layout_centerhorizontal="true" android:background="@drawable/level3" > <imagebutton android:id="@+id/level3_channel1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentbottom="true" android:layout_marginbottom="10dp" android:layout_marginleft="12dp" android:background="@drawable/channel1" /> <imagebutton android:id="@+id/level3_channel2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@id/level3_channel1" android:layout_marginbottom="17dp" android:layout_marginleft="-5dp" android:layout_torightof="@id/level3_channel1" android:background="@drawable/channel2" /> <imagebutton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@id/level3_channel2" android:layout_marginbottom="15dp" android:layout_marginleft="13dp" android:layout_torightof="@id/level3_channel2" android:background="@drawable/channel3" /> <imagebutton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerhorizontal="true" android:layout_margintop="10dp" android:background="@drawable/channel4" /> <imagebutton android:id="@+id/level3_channel7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentbottom="true" android:layout_alignparentright="true" android:layout_marginbottom="10dp" android:layout_marginright="12dp" android:background="@drawable/channel7" /> <imagebutton android:id="@+id/level3_channel6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@id/level3_channel7" android:layout_marginbottom="17dp" android:layout_marginright="-5dp" android:layout_toleftof="@id/level3_channel7" android:background="@drawable/channel6" /> <imagebutton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@id/level3_channel6" android:layout_marginbottom="15dp" android:layout_marginright="13dp" android:layout_toleftof="@id/level3_channel6" android:background="@drawable/channel5" /> </relativelayout> </relativelayout>
这里是一个相对布局中嵌套了三个相对布局,嵌套的第一个相对布局负责显示一级菜单,嵌套的第二个相对布局负责显示二级菜单,嵌套的第三个相对布局负责显示三级菜单。三个不同层次的菜单的背景都是弧形。我们通过指定具体的宽高来使三个层次的菜单具有不同的大小。
效果如下:
再看看mainactivity.java
/** * 模仿优酷菜单 * 2015年5月19日 */ public class mainactivity extends activity { //分别拿到不同等级的菜单 private relativelayout lv1; private relativelayout lv2; private relativelayout lv3; private animation animation; //各级菜单是否显示,默认全都显示 private boolean isdisplaylv1 = true; private boolean isdisplaylv2 = true; private boolean isdisplaylv3 = true; //动画是否正在执行,默认动画没有执行 private boolean isanimationrunning = false; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); lv1 = (relativelayout) this.findviewbyid(r.id.menu_level1); lv2 = (relativelayout) this.findviewbyid(r.id.menu_level2); lv3 = (relativelayout) this.findviewbyid(r.id.menu_level3); } @override public boolean onkeydown(int keycode, keyevent event) { //如果动画正在执行,则不处理此事件 if (isanimationrunning) return super.onkeydown(keycode, event); //如果点击的是菜单键 if (keycode == keyevent.keycode_menu) { //如果一级菜单已经显示,判断二级菜单是否显示 if (isdisplaylv1) { //设置动画启动延迟时间 int startoffset = 0; //如果二级菜单已经显示,判断三级菜单是否显示,然后退出二级菜单 if (isdisplaylv2) { if (isdisplaylv3) { //如果三级菜单已经显示,执行退出动画 exitanimation(lv3, startoffset); //三级菜单退出动画执行完毕之后,动画的启动时间延迟500ms startoffset += 500; isdisplaylv3 = !isdisplaylv3; } //二级菜单退出,此时startoffset=500,即动画启动时间延迟500ms exitanimation(lv2, startoffset); //二级菜单退出动画执行完毕之后,动画的启动时间延迟500ms startoffset += 500; isdisplaylv2 = !isdisplaylv2; } //一级菜单退出,此时startoffset=1000,即动画启动时间延迟1000ms exitanimation(lv1, startoffset); //如果一级菜单未显示,则一级菜单进入 } else { enteranimation(lv1); } isdisplaylv1 = !isdisplaylv1; return true; } return super.onkeydown(keycode, event); } public void myclick(view v) { //如果动画正在执行,则不处理此事件 if (isanimationrunning) return; switch (v.getid()) { /** * 当点击二级菜单的menu时,如果三级菜单已经显示,则执行退出动画, * 否则执行进入动画 */ case r.id.level2_menu: if (isdisplaylv3) { exitanimation(lv3, 0); } else { enteranimation(lv3); } isdisplaylv3 = !isdisplaylv3; break; case r.id.level1_home: // 如果二级菜单已经显示,再判断三级菜单是否显示 if (isdisplaylv2) { //通过设置动画启动延迟时间,来实现动画依次退出效果 int startoffset = 0; // 如果三级菜单也显示了,则让他们依次退出 if (isdisplaylv3) { exitanimation(lv3, startoffset); startoffset = 700; isdisplaylv3 = !isdisplaylv3; } exitanimation(lv2, startoffset); isdisplaylv2 = !isdisplaylv2; // 如果二级菜单没有显示,就让二级菜单显示出来 } else { enteranimation(lv2); isdisplaylv2 = !isdisplaylv2; } break; } } /** * 退出动画 * @param layout 执行动画的布局文件 * @param startoffset 动画启动的延迟时间 */ public void exitanimation(relativelayout layout, long startoffset) { animation = animationutils.loadanimation(this, r.anim.exit_menu); animation.setfillafter(true); animation.setstartoffset(startoffset); animation.setanimationlistener(new myanimationlistener()); layout.startanimation(animation); } /** * 进入动画 * @param layout 执行动画的布局文件 */ public void enteranimation(relativelayout layout) { animation = animationutils.loadanimation(this, r.anim.enter_menu); animation.setfillafter(true); animation.setanimationlistener(new myanimationlistener()); layout.startanimation(animation); } /** * 判断动画是否正在执行 * @author 王松 * */ private class myanimationlistener implements animationlistener { //动画开始执行 @override public void onanimationstart(animation animation) { isanimationrunning = true; } //动画执行结束 @override public void onanimationend(animation animation) { isanimationrunning = false; } @override public void onanimationrepeat(animation animation) { } } }
代码中注释已经写的很详细了,这里不再赘述。最后在给大家看看两个动画文件:
enter_menu.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareinterpolator="true"> <rotate android:duration="1000" android:fromdegrees="-180" android:todegrees="0" android:pivotx="50%" android:pivoty="100%" /> </set>
exit_menu.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareinterpolator="true"> <rotate android:duration="1000" android:fromdegrees="0" android:todegrees="-180" android:pivotx="50%" android:pivoty="100%" /> </set>
关于动画如果不太懂可以看这里:android基础知识之tween动画效果 android基础知识之frame动画效果
源码下载:http://xiazai.jb51.net/201606/yuanma/androidyouku(jb51.net).rar
原文链接:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。