当前位置: 移动技术网 > IT编程>移动开发>Android > Android自定义控件之仿优酷菜单

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

2019年07月24日  | 移动技术网IT编程  | 我要评论

暧昧青葱事件txt,中国好舞蹈金星怒斥导演,天高任鸟飞

去年的优酷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动画效果

源码下载:

原文链接:

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网