热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

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

这篇文章主要为大家详细介绍了Android自定义控件之仿优酷菜单的相关资料,感兴趣的小伙伴们可以参考一下

去年的优酷HD版有过这样一种菜单,如下图:

这里写图片描述

应用打开之后,先是三个弧形的三级菜单,点击实体键menu之后,这三个菜单依次旋转退出,再点击实体键menu之后,一级菜单会旋转进入,点击一级菜单,二级菜单旋转进入,点击二级菜单的menu键,三级菜单旋转进入,再次点击二级菜单的旋转键,三级菜单又会旋转退出,这时再点击一级菜单,二级菜单退出,最后点击实体menu键,一级菜单退出。

总体来说实现这样的功能:
(1)点击实体menu键时,如果界面上有菜单显示,不管有几个,全部依次退出,如果界面上没有菜单显示,则显示一级菜单。
(2)点击一级菜单的home键时,如果此时界面只有一级菜单,则显示二级菜单,否则让除了一级菜单外的菜单全都依次退出。
(3)点击二级菜单的menu键时,如果三级菜单已经显示,则让它旋转退出,如果三级菜单未显示则让它旋转进入。

好了,今天我们主要实现上述效果。

先来看布局文件



 

  
 

 

  

  

  
 

 

  

  

  

  

  

  

  
 


这里是一个相对布局中嵌套了三个相对布局,嵌套的第一个相对布局负责显示一级菜单,嵌套的第二个相对布局负责显示二级菜单,嵌套的第三个相对布局负责显示三级菜单。三个不同层次的菜单的背景都是弧形。我们通过指定具体的宽高来使三个层次的菜单具有不同的大小。

效果如下:

这里写图片描述

再看看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

<&#63;xml version="1.0" encoding="utf-8"&#63;>

 

exit_menu.xml

<&#63;xml version="1.0" encoding="utf-8"&#63;>

 


关于动画如果不太懂可以看这里:Android基础知识之tween动画效果    Android基础知识之frame动画效果

源码下载:http://xiazai.jb51.net/201606/yuanma/Androidyouku(jb51.net).rar

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

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


推荐阅读
  • 转载自:http:blog.csdn.netCodingEndingarticledetails78609902#t14保存标签2018-03-09blog.csdn ... [详细]
  • Android开发技巧:深入探讨数据存储方法
    Android开发技巧:深入探讨数据存储方法 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了QtForAndroid之启动页相关的知识,希望对你有一定的参考价值。启动页 ... [详细]
  • excl剔除不合格数据求平均值trimmean函数正态分布:CONFIDE ... [详细]
  • 之前一直想着建图。。。遍历可是推例子都不正确后来看数据好像看出了点规律就抱着试一试的心态水了一下就。。。。过了。。。。。后来想想我的思路还是对的先抽象当前仅仅有两个点相连想要拆分耗 ... [详细]
  • 最近在网上下载了myeclipse2015的stable2.0版本做平时练习使用,但是正版的myeclipse是需要付费的,所以就找了一个破解方法,下面是破解步骤。myeclips ... [详细]
  • 关于Ajax异步请求(实时刷新)
    1.需求:想要做成动态实时刷新获取数据库的值2.例子3.代码逻辑:varSeconds10000;varurl' ... [详细]
  • 系统用户登录Oracle(2)
    Oracle默认的系统用户:1.syssystem2.sysman3.scottsys:拥有的权限最大,可以完成数据库所有的管理任务system:通常用来查看管理信息的表或者视图s ... [详细]
  • osi七层协议的作用1、规范了厂商之间的设备通讯2、保证了每层的功能帧是数据链路层的包是网络层的hub的基本原理一条总线一个冲突域一个广播域工作原理冲突检测和半双工的工作模式网线为 ... [详细]
  • 将自己学的知识整合了一下,弄了个小的图论系统。有关知识请看:http:blog.csdn.netcolumndetailstulun.html#include#i ... [详细]
  • 阶段1 语言基础+高级_13Java语言高级_04集合_01 Collection集合_5_迭代器的代码实现
    迭代器的类型和collection一样。都是String类型的判断集合内是不是有元素取出第一个元素多次next获取所有的值没有元素,再去取就会抛出异常。适应whilefor循环的格 ... [详细]
  • 一、echo设置字体颜色表示方法echo–e“\033[3#;4#;#语句\033[0m”3#,代表控制前景色4#,代表控制背景色#,代表字符格式(加粗、下划线、闪烁等)3#中的# ... [详细]
  • 我正在构建一个需要蓝牙键盘字母按键事件并强制取消聚焦各个编辑区域的APK。TalkB ... [详细]
  • NOIP提高组 2011
    题目描述丽江河边有n家很有特色的客栈,客栈按照其位置顺序从1到n编号。每家客栈都按照某一种色调进行装饰(总共k种,用整数0~k-1表示),且每家客栈都设有一家咖啡店,每家咖啡店均有 ... [详细]
  • vi常用命令行1.vi模式a)一般模式:vi处理文件时,一进入该文件,就是一般模式了.b)编辑模式:在一般模式下可以进行删除,复制,粘贴等操作,却无法进行编辑操作。等按下‘i,I, ... [详细]
author-avatar
烟熏装-_265
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有