首页 > 系统 > Android > 正文

Android自定义控件之仿优酷菜单

2019-12-12 06:14:00
字体:
来源:转载
供稿:网友

去年的优酷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.VeVB.COm/201606/yuanma/Androidyouku(VeVB.COm).rar

原文链接:http://blog.csdn.net/u012702547/article/details/45842963

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表