转载本博客请注明出处:点击打开链接  http://blog.csdn.net/qq_32059827/article/details/52327456

今天这篇稍微增强点代码量,可能要多花上5分钟喽。

本篇完成一个稍微显得绚丽的菜单项,模仿优酷选择菜单。如果想对其中的任意一项实现点击功能,自行加入即可。

现在就一步一步做出这个小案例:

在实现功能前,先看一下完成的结果,可能能对代码更好的理解。

效果演示:

PS:由于代码中做出了详细的解释,不再做过多的赘述。

首先自定义组合控件布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" > <RelativeLayout
android:id="@+id/rl_level3"
android:layout_width="320dip"
android:layout_height="160dip"
android:layout_alignParentBottom="true"
android:background="@drawable/level3" > <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="8dip"
android:background="@drawable/channel4" /> <ImageButton
android:id="@+id/iv_channel1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="5dip"
android:layout_marginLeft="12dip"
android:background="@drawable/channel1" /> <ImageButton
android:id="@+id/iv_channel2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/iv_channel1"
android:layout_marginBottom="16dip"
android:layout_marginLeft="35dip"
android:background="@drawable/channel2" /> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/iv_channel2"
android:layout_marginBottom="16dip"
android:layout_marginLeft="70dip"
android:background="@drawable/channel3" /> <ImageButton
android:id="@+id/iv_channel7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="5dip"
android:layout_marginRight="12dip"
android:background="@drawable/channel7" /> <ImageButton
android:id="@+id/iv_channel6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/iv_channel7"
android:layout_alignParentRight="true"
android:layout_marginBottom="16dip"
android:layout_marginRight="35dip"
android:background="@drawable/channel6" /> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/iv_channel6"
android:layout_alignParentRight="true"
android:layout_marginBottom="16dip"
android:layout_marginRight="70dip"
android:background="@drawable/channel5" />
</RelativeLayout> <RelativeLayout
android:id="@+id/rl_level2"
android:layout_width="200dip"
android:layout_height="100dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level2" > <ImageButton
android:id="@+id/ib_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="8dip"
android:background="@drawable/icon_menu" /> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="5dip"
android:layout_marginLeft="12dip"
android:background="@drawable/icon_search" /> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="5dip"
android:layout_marginRight="12dip"
android:background="@drawable/icon_myyouku" />
</RelativeLayout> <RelativeLayout
android:id="@+id/rl_level1"
android:layout_width="100dip"
android:layout_height="50dip"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level1"
android:gravity="center" > <ImageButton
android:id="@+id/ib_home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/icon_home" />
</RelativeLayout> </RelativeLayout>

因为动画不断地使用,选择定义一个动画效果的utils类:

package com.itydl.yukudemo.Utils;

import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.RotateAnimation;
import android.widget.RelativeLayout; /**
* 这是专门设置动画操作的工具类
* @author lenovo
*
*/ public class MyAnimationUtils { private static int runningAnimation = 0;//是否存在动画播放的标志位 public static boolean isRunningAnimation(){
return runningAnimation!=0;
} /**
* 开始旋转隐藏的动画
* @param v
* 要给哪个view加动画
*/
public static void startRotateHindeAnimation(RelativeLayout v){
//复用动画方法,这里是不延时动画 startRotateHindeAnimation(v,0);
} /**
* 带有延时效果的动画
* @param v
* 要给哪个组件加入动画
* @param startOffset
* 延时时间,传递过来
*/
public static void startRotateHindeAnimation(RelativeLayout v,long startOffset){
//如果当前的动画隐藏了,该view动画上边的控件的事件也要阉割掉
for(int i = 0 ;i< v.getChildCount(); i ++){
v.getChildAt(i).setEnabled(false);//view.getChildAt(i)获取索引位置的子控件实例;setEnabled(false);禁用事件
}
RotateAnimation ra = new RotateAnimation(
0, -180,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 1f);
ra.setDuration(500);
ra.setFillAfter(true);//设置动画执行完毕,控件状态停留在结束状态
//设置动画监听状态
ra.setAnimationListener(animationListener);
//加入延时
ra.setStartOffset(startOffset);
//给哪个view加动画,传递过来这个view
v.startAnimation(ra); } /**
* 旋转显示的动画
* @param v
* 要给哪个view加动画
*/
public static void startRotateShowAnimation(RelativeLayout v){
startRotateShowAnimation(v, 0);
} /**
* 延时显示动画
* @param v
* 要给哪个view加动画
* @param startOffset
* 设置动画延时时间,传递过来
*/
public static void startRotateShowAnimation(RelativeLayout v,int startOffset){ //设置如果当前的view显示,让该view子控件也都重新获取事件
for(int i = 0 ;i< v.getChildCount(); i ++){
v.getChildAt(i).setEnabled(true);//view.getChildAt(i)获取索引位置的子控件实例;setEnabled(true);启动事件
}
RotateAnimation ra = new RotateAnimation(
-180, 0,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 1f);
ra.setDuration(500);
ra.setFillAfter(true);//设置动画执行完毕,控件状态停留在结束状态
//设置动画监听状态
ra.setAnimationListener(animationListener);
//延时播放动画
ra.setStartOffset(startOffset);
//给哪个view加动画,传递过来这个view
v.startAnimation(ra);
} static AnimationListener animationListener = new AnimationListener() { //开始播放
@Override
public void onAnimationStart(Animation animation) {
// 播放一个动画,说明存在一个动画在播放
runningAnimation ++ ; } @Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub } //播放结束
@Override
public void onAnimationEnd(Animation animation) {
// 动画播放完毕
runningAnimation -- ; }
}; }

MainActivity的代码如下:

package com.itydl.yukudemo;

import com.itydl.yukudemo.Utils.MyAnimationUtils;

import android.os.Bundle;
import android.app.Activity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.RelativeLayout; public class MainActivity extends Activity { private RelativeLayout mRl_Level1;
private RelativeLayout mRl_Level2;
private RelativeLayout mRl_Level3;
private ImageButton mIb_Home;
private ImageButton mIb_Menu; private boolean level3 = true;//设置标志位,对状态改变标记;三级菜单默认状态为显示。(注意这种编程思想)
private boolean level2 = true;//设置标志位,对状态改变标记;二级菜单默认状态为显示。(注意这种编程思想)
private boolean level1 = true;//设置标志位,对状态改变标记;一级菜单默认状态为显示。(注意这种编程思想) @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initEvent();
} /**
* 初始化事件
*/
private void initEvent() { // 对menu和home按钮加入点击事件
OnClickListener listener = new OnClickListener() { @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.ib_home:// 点击的是home键
//解决连续点击按钮,动画播放不完
if(MyAnimationUtils.isRunningAnimation()){
return;
}
int longTime = 0;
if(level2){
if(level3){
//如果三级菜单显示,点击home键,应该让其也消失
MyAnimationUtils.startRotateHindeAnimation(mRl_Level3);
level3 = false;
//进入这里,说明开始三级菜单为显示状态。延时增加
longTime = 200;
}
//显示,点击应该隐藏
MyAnimationUtils.startRotateHindeAnimation(mRl_Level2,longTime);
//修改状态值
level2 = false;
}else{
//隐藏状态,应该显示
MyAnimationUtils.startRotateShowAnimation(mRl_Level2);
//修改状态值
level2 = true;
} break;
case R.id.ib_menu:// 点击的是menu键
if(MyAnimationUtils.isRunningAnimation()){
//保证动画播放完毕再播放一次播放
return;
}
//判断三级菜单的状态
if(level3){
//显示,点击应该隐藏
MyAnimationUtils.startRotateHindeAnimation(mRl_Level3);
//修改状态值
level3 = false;
}else{
//隐藏状态,应该显示
MyAnimationUtils.startRotateShowAnimation(mRl_Level3);
//修改状态值
level3 = true;
}
break; default:
break;
} }
}; mIb_Home.setOnClickListener(listener);
mIb_Menu.setOnClickListener(listener); } //手机的menu键按下的时候调用事件
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(level1){
int longTime = 0;
//判断二级菜单是否显示
if(level2){
//判断三级菜单是否显示
if(level3){
//隐藏三级菜单
MyAnimationUtils.startRotateHindeAnimation(mRl_Level3);
level3 = false;
longTime = 200;//延时标记
}
//隐藏二级菜单
MyAnimationUtils.startRotateHindeAnimation(mRl_Level2,longTime);
level2 = false;
longTime += 200;
}
//一级菜单显示状态
//隐藏一级菜单
MyAnimationUtils.startRotateHindeAnimation(mRl_Level1,longTime);
level1 = false;
}else{
//一次显示
MyAnimationUtils.startRotateShowAnimation(mRl_Level1);
MyAnimationUtils.startRotateShowAnimation(mRl_Level2,200);
MyAnimationUtils.startRotateShowAnimation(mRl_Level3,400);
level1 = true;
level2 = true;
level3 = true;
}
// 交由父类去处理逻辑,自己不做处理
return super.onKeyDown(keyCode, event);
} /**
* 初始化界面
*/
private void initView() { mRl_Level1 = (RelativeLayout) findViewById(R.id.rl_level1);
mRl_Level2 = (RelativeLayout) findViewById(R.id.rl_level2);
mRl_Level3 = (RelativeLayout) findViewById(R.id.rl_level3); mIb_Home = (ImageButton) findViewById(R.id.ib_home);
mIb_Menu = (ImageButton) findViewById(R.id.ib_menu); }
}

好啦,赶快把代码复制到您的IDE中把效果跑起来吧!

欢迎关注本博客点击打开链接  http://blog.csdn.net/qq_32059827,每天花上5分钟,阅读一篇有趣的安卓小文哦。

Android简易实战教程--第二十三话《绚丽的菜单项》的更多相关文章

  1. Android简易实战教程--第二十七话《自定义View入门案例之开关按钮详细分析》

    转载此博客请注明出处点击打开链接       http://blog.csdn.net/qq_32059827/article/details/52444145 对于自定义view,可能是一个比较大的 ...

  2. Android简易实战教程--第二十话《通过广播接收者,对拨打电话外加ip号》

    没睡着觉,起来更篇文章吧哈哈!首先祝贺李宗伟击败我丹,虽然我是支持我丹的,但是他也不容易哈哈,值得尊敬的人!切入正题:这一篇来介绍个自定义广播接收者. 通常我们在外拨电话的时候,一般为使用网络电话.如 ...

  3. Android简易实战教程--第十三话《短信备份和还原~三》

    之前写过短信备份的小案例,哪里仅仅是虚拟了几条短信信息.本篇封装一个业务类,且直接通过内容提供者,访问本系统的短信信息,再提供对外接口.如果想要短信备份和短信还原,直接复制这段代码即可.对于您调用这个 ...

  4. Android简易实战教程--第二十九话《创建图片副本》

    承接第二十八话加载大图片,本篇介绍如何创建一个图片的副本. 安卓中加载的原图是无法对其修改的,因为默认权限是只读的.但是通过创建副本,就可以对其做一些修改,绘制等了. 首先创建一个简单的布局.一个放原 ...

  5. Android简易实战教程--第二十六话《网络图片查看器在本地缓存》

    本篇接第二十五话  点击打开链接   http://blog.csdn.net/qq_32059827/article/details/52389856 上一篇已经把王略中的图片获取到了.生活中有这么 ...

  6. Android简易实战教程--第二话《两种进度条》

    点击按钮模拟进度条下载进度,"下载"完成进度条消失. 代码如下: xml: <?xml version="1.0" encoding="utf- ...

  7. Android简易实战教程--第二十八话《加载大图片》

    Android系统以ARGB表示每个像素,所以每个像素占用4个字节,很容易内存溢出.假设手机内存比较小,而要去加载一张像素很高的图片的时候,就会因为内存不足导致崩溃.这种异常是无法捕获的 内存不足并不 ...

  8. Android简易实战教程--第二十五话《网络图片查看器》

    访问网络已经有了很成熟的框架.这一篇只是介绍一下HttpURLConnection的简单用法,以及里面的"注意点".这一篇可以复习或者学习HttpURLConnection.han ...

  9. Android简易实战教程--第二十四话《画画板》

    今天完成一个画画板. 首先来个布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android ...

随机推荐

  1. [HNOI 2001]求正整数

    Description 对于任意输入的正整数n,请编程求出具有n个不同因子的最小正整数m.例如:n=4,则m=6,因为6有4个不同整数因子1,2,3,6:而且是最小的有4个因子的整数. Input n ...

  2. 2015 多校联赛 ——HDU5372(树状数组)

    Sample Input 3 0 0 0 3 0 1 5 0 1 0 0 1 1 0 1 0 0   Sample Output Case #1: 0 0 0 Case #2: 0 1 0 2 有0, ...

  3. 修改SQL数据库中表字段类型时,报“一个或多个对象访问此列”错误的解决方法

    在SQL数据库中使用SQL语句(格式:alter table [tablename] alter column [colname] [newDataType])修改某表的字段类型时,报一下错误:由于一 ...

  4. h5 网页版的微博微信QQ登录

    一:微博 1,先说微博吧,首先你的去http://open.weibo.com/wiki/先注册账号,通过验证审核.然后的创建网页应用.微博审核不通过的原因就是域名和网站地址,一定要按实际写的.一定要 ...

  5. 电子凭证 : Java 生成 Pdf

    来源:蛙牛, my.oschina.net/lujianing/blog/894365 如有好文章投稿,请点击 → 这里了解详情 1.背景 在某些业务场景中,需要提供相关的电子凭证,比如网银/支付宝中 ...

  6. node的异常处理

    Node是单线程运行环境,一旦抛出的异常没有被捕获,就会引起整个进程的崩溃.所以,Node的异常处理对于保证系统的稳定运行非常重要. node的处理方法: 1.使用throw语句抛出异常 常用的捕获异 ...

  7. 百度音乐flac 下载

    破解百度音乐白金会员 为了给Play Music上传标签齐全的正版的mp3,本屌翻遍网络苦思冥想.现在终于被我找到了破解之法——破解百度白金会员!破解之后可以直接从百度下载正版授权的320k文件,更可 ...

  8. ABP文档笔记 - 数据过滤

    预定义的过滤 ISoftDelete 软删除过滤用来在查询数据库时,自动过滤(从结果中抽取)已删除的实体.如果一个实体可以被软删除,它必须实现ISoftDelete接口,该接口只定义了一个IsDele ...

  9. 01_Struts2概述及环境搭建

    1.Struts2概述: Struts2是一个用来开发MVC应用程序的框架. Struts2提供了web应用程序开发过程中一些常见问题的解决方案; 对用户输入的数据进行合法性验证 统一的布局 可扩展性 ...

  10. Node.js 加密

    稳定性: 2 - 不稳定; 正在讨论未来版本的 API 改进,会尽量减少重大变化.详见后文. 使用 require('crypto') 来访问这个模块. 加密模块提供了 HTTP 或 HTTPS 连接 ...