Android编程自定义菜单实现方法详解
作者:蓝之风 发布时间:2022-08-25 18:16:08
标签:Android,自定义,菜单
本文实例讲述了Android编程自定义菜单实现方法。分享给大家供大家参考,具体如下:
在android开发的过程中系统自带的菜单往往满足不了开发中的一些需求,比如说一排最多只能放置三个菜单,坐多只能放置6个,再多的话就会折叠起来,如果我们想再一排显示4个或5个菜单那么就要自己想办法处理。
这里我用布局的隐藏并加上动画来模拟菜单的效果。
要点:
1、隐藏和显示菜单,我使用了一个线性布局把菜单封装起来。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_alignParentBottom="true"
android:background="@drawable/menubackground"
android:layout_width="fill_parent"
android:layout_height="144px"
android:orientation="vertical"
android:gravity="center"
android:visibility="gone"
android:id="@+id/lines">
<LinearLayout android:orientation="horizontal"
android:gravity="center"
android:layout_width="fill_parent"
android:layout_height="72px"
>
<ImageButton
android:layout_marginLeft="8dip"
android:id="@+id/menu_btn_index"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/menu_index_selector"
/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/menu_news_selector"
android:id="@+id/menu_btn_news"
/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/menu_lib_selector"
android:id="@+id/menu_btn_lib"
/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/menu_add_selector"
android:id="@+id/menu_btn_add"
/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/menu_set_selector"
android:id="@+id/menu_btn_set"
/>
</LinearLayout>
<LinearLayout android:orientation="horizontal" android:gravity="center"
android:layout_width="fill_parent"
android:layout_height="72px">
<ImageButton
android:layout_marginLeft="8dip"
android:id="@+id/menu_btn_index"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/menu_index_selector"
/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/menu_news_selector"
android:id="@+id/menu_btn_news"
/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/menu_lib_selector"
android:id="@+id/menu_btn_lib"
/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/menu_add_selector"
android:id="@+id/menu_btn_add"
/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/menu_quit_selector"
android:id="@+id/menu_btn_quit"
/>
</LinearLayout>
</LinearLayout>
2、模拟菜单的效果,增加动画,布局显示的时候增加一个渐渐底部生气的效果,隐藏的时候增加一个缓缓下落的效果,显示菜单动画文件:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="0"
android:toXDelta="0"
android:fromYDelta="00"
android:toYDelta="140"
android:duration="200" />
</set>
隐藏菜单动画文件:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="0"
android:toXDelta="0"
android:fromYDelta="140"
android:toYDelta="00"
android:duration="200" />
</set>
动画调用:
/**
* 显示菜单栏, 重新实现的Option menu.
* */
private void showAppMenu() {
if (menuShowAnimation == null) {
menuShowAnimation = AnimationUtils
.loadAnimation(mContext, R.anim.menuhide);
}
myLayout.startAnimation(menuShowAnimation);
myLayout.setVisibility(View.VISIBLE);
}
/**
* 隐藏菜单栏, 重新实现的Option menu.
* */
private void hideAppMenu() {
myLayout.setVisibility(View.GONE);
if (menuHideAnimation == null)
menuHideAnimation =AnimationUtils
.loadAnimation(mContext, R.anim.menushow);
myLayout.startAnimation(menuHideAnimation);
}
3、控制菜单的隐藏和显示,需要重写三个方法public boolean onCreateOptionsMenu(Menu menu),
public boolean dispatchKeyEvent(KeyEvent event) 和public boolean dispatchTouchEvent(MotionEvent event)
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if(mCustomMenu==null)
mCustomMenu=new CustomMenu(CustomMenuActivity.this,CustomMenuActivity.this);
mCustomMenu.CreateMenu();
return false;
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if(mCustomMenu!=null)
return mCustomMenu.dispatchKeyEvent(event,super.dispatchKeyEvent(event));
return super.dispatchKeyEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if(mCustomMenu!=null)
return mCustomMenu.dispatchTouchEvent(event,super.dispatchTouchEvent(event));
return super.dispatchTouchEvent(event);
}
4、实现菜单点击时候被点击菜单状态的般变化,这里我使用了selector来实现,菜单我使用ImageButton将selector赋值给ImageButton 的background即可:
一个菜单项
<ImageButton
android:layout_marginLeft="8dip"
android:id="@+id/menu_btn_index"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/menu_index_selector"
/>
menu_index_selector 文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2009 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false"
android:drawable="@drawable/menu_index" />
<item android:state_pressed="true"
android:drawable="@drawable/menu_index1" />
<item android:state_focused="true"
android:drawable="@drawable/menu_index1" />
<item
android:drawable="@drawable/menu_index" />
</selector>
5、页面的调用使用:<include>标签来进行引用:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<include layout="@layout/menu_layout"/>
</RelativeLayout>
这样的话一个模拟的自定义菜单就基本完成了,菜单控制完整代码java类:
package com.demo.utils;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import com.demo.HelloWorld.R;
/**
* @author Administrator
* xsl xushilin@kingtoneinfo.com
* @version: 创建时间:2011-8-30 上午11:16:19
* 说 明:
* 修改历史:
*/
public class CustomMenu {
private LinearLayout myLayout;
private Context mContext;
private Activity mActivity;
private Animation menuShowAnimation = null;
private Animation menuHideAnimation = null;
private Resources res;
public int screen_height;
private ImageButton imgIndex,imgSet,imgNews,imgAdd,imgQuit,imgLib;
public CustomMenu(Context context,Activity activity){
mContext=context;
mActivity=activity;
res = mContext.getResources();
screen_height = res.getDisplayMetrics().heightPixels;
myLayout=(LinearLayout)activity.findViewById(R.id.lines);
imgIndex=(ImageButton)activity.findViewById(R.id.menu_btn_index);
imgSet=(ImageButton)activity.findViewById(R.id.menu_btn_set);
imgNews=(ImageButton)activity.findViewById(R.id.menu_btn_news);
imgAdd=(ImageButton)activity.findViewById(R.id.menu_btn_add);
imgQuit=(ImageButton)activity.findViewById(R.id.menu_btn_quit);
imgLib=(ImageButton)activity.findViewById(R.id.menu_btn_lib);
//返回首页
imgIndex.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
//TODO do somthing
}
});
//设置
imgSet.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
//TODO do somthing
}
});
//查询
imgNews.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
//TODO do somthing
}
});
//编辑
imgAdd.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
//TODO do somthing
}
});
//退出系统
imgQuit.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
//TODO do somthing
}
});
//素材库
imgLib.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
//TODO do somthing
}
});
}
public void CreateMenu(){
if(myLayout.getVisibility()==View.GONE)
showAppMenu();
//myLayout.setVisibility(View.VISIBLE);
else
hideAppMenu();
//myLayout.setVisibility(View.GONE);
}
/**
* 显示菜单栏, 重新实现的Option menu.
* */
private void showAppMenu() {
if (menuShowAnimation == null) {
menuShowAnimation = AnimationUtils
.loadAnimation(mContext, R.anim.menuhide);
}
myLayout.startAnimation(menuShowAnimation);
myLayout.setVisibility(View.VISIBLE);
}
/**
* 隐藏菜单栏, 重新实现的Option menu.
* */
private void hideAppMenu() {
myLayout.setVisibility(View.GONE);
if (menuHideAnimation == null)
menuHideAnimation =AnimationUtils
.loadAnimation(mContext, R.anim.menushow);
myLayout.startAnimation(menuHideAnimation);
}
public boolean dispatchTouchEvent(MotionEvent event,boolean b) {
if (myLayout.getVisibility() == View.VISIBLE) {
int y = (int) event.getRawY();
if (y < screen_height - myLayout.getHeight()) {
hideAppMenu();
return true;
}
}
return b;
}
public boolean dispatchKeyEvent(KeyEvent event,boolean b) {
int act = event.getAction();
int code = event.getKeyCode();
// app menu like option menu
if (code == KeyEvent.KEYCODE_MENU){
if (act == KeyEvent.ACTION_DOWN){
if (myLayout.getVisibility() == View.VISIBLE) {
hideAppMenu();
} else {
showAppMenu();
}
return true;
}
}else if (code == KeyEvent.KEYCODE_BACK){
if (myLayout.getVisibility() == View.VISIBLE) {
hideAppMenu();
return true;
}
}
return b;
}
}
activity调用菜单完整代码:
package com.demo.ui;
import com.demo.HelloWorld.R;
import com.demo.utils.CustomMenu;
import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MotionEvent;
/**
* @author XSL
* xsl xushilin@kingtoneinfo.com
* @version: 创建时间:2011-8-30 上午11:13:14
* 说 明:
* 修改历史:
*/
public class CustomMenuActivity extends Activity {
private CustomMenu mCustomMenu=null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_menu);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if(mCustomMenu==null)
mCustomMenu=new CustomMenu(CustomMenuActivity.this,CustomMenuActivity.this);
mCustomMenu.CreateMenu();
return false;
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if(mCustomMenu!=null)
return mCustomMenu.dispatchKeyEvent(event,super.dispatchKeyEvent(event));
return super.dispatchKeyEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if(mCustomMenu!=null)
return mCustomMenu.dispatchTouchEvent(event,super.dispatchTouchEvent(event));
return super.dispatchTouchEvent(event);
}
}
实现的效果如下:
希望本文所述对大家Android程序设计有所帮助。
0
投稿
猜你喜欢
- java中的final关键字详解final的作用随着所修饰的类型而不同  
- 免责声明:本教程所有资源均来源于网络;仅用于学习交流,请勿用于任何商业行为;如需要,请使用正版授权;侵权联删。推荐最新 IntelliJ I
- 我相信现在绝大部分App几乎避免不了消息推送,其实原理还是使用了长连接,通过服务端将消息推给客户端。市面上也有不少三方库,例如极光、友盟、个
- 协议做如下规定:规定数据协议:序列号 长度 状态字 数据长度 数据1 &n
- 父类空间优先于子类对象产生在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空间,便可以包含
- 对于javascript的冒泡,我一直误解它了,冒泡,即是从底层往外blow blow blow ...惭愧的是,我一直以为阻止冒泡是阻止父
- 引言最近,因为开发的时候经改动依赖的库,所以,我想对 Gradle 脚本做一个调整,用来动态地将依赖替换为源码。这里以 android-mv
- springboot中集成jpa需要再pom文件中添加jpa的jar包,使用springboot的话iju不用自己规定版本号了,自动管理依赖
- mybatis Integer类型参数动态sql注意条件例如以下拼接的动态sql<if test="work_status
- 前一篇博文介绍了JDK logging基础知识 博文中也提到LogManager,本章主要阐述怎么完全定制化LogManager来
- 1、获取表中最后一条数据public static String demo() throws SQLException { String s
- 这篇文章介绍使用设计模式中的策略模式和委托来解决多个IfElse判断语句和Switch语句,这种替换方式在其他语言也一样可以做到,比如PHP
- 前言老规矩,还是从最简单粗暴的开始。那么多简单算简单?多粗暴算粗暴?我告诉你可以不写一句代码,你信吗?直接把一个文件往IIS服务器上一扔,就
- EasyCode 插件EasyCode 插件 是一款根据表结构生成代码的很方便的Idea插件, 强烈推荐. 并且可以自定义模板来控制生成的类
- 一、@Configuration1.1 未加@Configuration<!--logback-test.xml,配置不打印日志--&
- 一、前言在java中,异常机制是非常有用的构成部分,异常信息对于查找错误来说是必不可少至关重要的信息,因此我们希望在发生错误的时候先看到捕捉
- 前言我采用的是Camera来实现自定义相机的,如果你使用的是Camera2,那本文将不适用你。为了减少篇幅,本文主要讲解手动对焦的实现方式,
- 本文实例讲述了c#中datagridview处理非绑定列的方法。分享给大家供大家参考。具体实现方法如下:using System;using
- 1.Context的应用Context在启动协程模式中就已经遇到过叫CoroutineContext,它的意思就是协程上下文,线程的切换离不
- 在编程过程中一定要注意代码命名的规范性,否则在使用和维护过程中将造成很大的麻烦,这也是一种良好的编码习惯。看下面代码,除了userPass命