SecondDay_Menu菜单

本文详细介绍Android应用中三种常见菜单的实现方法:系统菜单OptionsMenu、上下文菜单ContextMenu及弹出菜单PopupMenu。通过步骤解析与代码示例,帮助开发者掌握菜单创建与事件监听技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

常用的Menu菜单

在这里插入图片描述

一、系统菜单OptionsMenu

步骤

效果图看下:
在这里插入图片描述
1、首先写这个系统菜单,现在res资源文件目录下,建一个menu格式的文件夹创建一个xml布局文件
在这里插入图片描述
2、接下来写Activity.xml布局文件写一个空间(主要是看颜色变化效果就写了一个TextView)
在这里插入图片描述
3、接下来是代码
(1)、Activity重写onCreateOptionsMenu加载资源文件
(2)、Activity重写onOptionsItemSelected设置事件监听
在这里插入图片描述

2、上下文菜单ContextMenu

效果图先看下:
在这里插入图片描述

步骤

1、先写一个xml布局文件
在这里插入图片描述
2、这个其实写的一个menu布局复用接上一个的,代码效果一样
接下来看代码:
在这里插入图片描述

三、弹出菜单PapupMenu

步骤

效果图:
在这里插入图片描述
1、其中的menu文件还是复用第一个的Menu文件,效果还是一样的

这个是xml文件
在这里插入图片描述
2、接下来就是代码图:
在这里插入图片描述
注意:弹出菜单默认弹出的框在控件下方

#!/system/bin/sh # 双缓冲倒计时脚本 - 修复显示和输入错误问题 # 初始化变量 target_year=0 target_month=0 target_day=0 target_hour=0 target_minute=0 target_second=0 remaining_seconds=0 is_paused=true is_running=false last_update=0 refresh_rate=1 # 刷新频率(秒) # 双缓冲系统初始化 init_double_buffer() { # 创建两个临时文件作为缓冲区 buffer1=$(mktemp) buffer2=$(mktemp) # 设置当前显示缓冲区和后台缓冲区 current_buffer=$buffer1 back_buffer=$buffer2 # 隐藏光标 echo -ne "\033[?25l" # 保存初始光标位置 echo -ne "\033[s" } # 切换缓冲区 swap_buffers() { # 恢复光标到初始位置 echo -ne "\033[u" # 清除从光标到屏幕末尾的内容 echo -ne "\033[J" # 显示后台缓冲区内容 cat $back_buffer # 交换缓冲区 temp=$current_buffer current_buffer=$back_buffer back_buffer=$temp # 清空新的后台缓冲区 > $back_buffer } # 绘制内容到后台缓冲区 draw_to_back_buffer() { # 将内容追加到后台缓冲区 echo -e "$@" >> $back_buffer } # 清理资源 cleanup() { # 显示光标 echo -ne "\033[?25h" # 删除临时文件 rm -f $buffer1 $buffer2 # 清屏 echo -ne "\033[2J\033[H" } # 计算剩余秒数 calculate_remaining() { current_epoch=$(date +%s) # 计算目标时间的Unix时间戳 target_date="${target_year}-${target_month}-${target_day} ${target_hour}:${target_minute}:${target_second}" target_epoch=$(date -d "$target_date" +%s 2>/dev/null) if [ -z "$target_epoch" ]; then draw_to_back_buffer "错误:无效的日期格式" return 1 fi remaining_seconds=$((target_epoch - current_epoch)) return 0 } # 格式化时间显示 format_time() { local seconds=$1 # 计算总天数 local total_days=$((seconds / 86400)) local years=$((seconds / 31536000)) seconds=$((seconds % 31536000)) local months=$((seconds / 2592000)) seconds=$((seconds % 2592000)) local days=$((seconds / 86400)) seconds=$((seconds % 86400)) local hours=$((seconds / 3600)) seconds=$((seconds % 3600)) local minutes=$((seconds / 60)) local secs=$((seconds % 60)) # 优化显示格式 printf "总天数:%d | %d年%02d月%02d日 %02d:%02d:%02d" $total_days $years $months $days $hours $minutes $secs } # 更新剩余时间 update_remaining() { if [ $is_running = true ] && [ $is_paused = false ]; then current_time=$(date +%s) # 确保每秒只更新一次 if [ $current_time -gt $last_update ]; then if [ $remaining_seconds -gt 0 ]; then remaining_seconds=$((remaining_seconds - 1)) last_update=$current_time return 0 # 需要刷新 else # 时间到处理 is_running=false draw_to_back_buffer "时间到!" echo -e "\a" # 发出提示音 return 1 # 需要刷新 fi fi fi return 2 # 不需要刷新 } # 构建菜单内容 build_menu() { # 清空后台缓冲区 > $back_buffer # 绘制菜单框架 draw_to_back_buffer "======== 双缓冲倒计时菜单 ========" draw_to_back_buffer "1. 设置目标时间" draw_to_back_buffer "2. 开始倒计时" draw_to_back_buffer "3. 暂停/继续" draw_to_back_buffer "4. 重置倒计时" draw_to_back_buffer "5. 退出程序" draw_to_back_buffer "===============================" # 显示目标时间 draw_to_back_buffer "当前目标: " if [ $target_year -ne 0 ]; then draw_to_back_buffer " $(printf "%d-%02d-%02d %02d:%02d:%02d" $target_year $target_month $target_day $target_hour $target_minute $target_second)" else draw_to_back_buffer " 未设置" fi # 显示剩余时间 draw_to_back_buffer "剩余时间: " if [ $target_year -ne 0 ]; then if [ $is_running = true ] && [ $is_paused = false ]; then # 动态更新模式 draw_to_back_buffer " $(format_time $remaining_seconds) [运行中]" else # 静态显示模式 if calculate_remaining; then draw_to_back_buffer " $(format_time $remaining_seconds) [暂停]" else draw_to_back_buffer " 计算错误" fi fi else draw_to_back_buffer " 未设置" fi draw_to_back_buffer "===============================" draw_to_back_buffer "请选择操作 [1-5]: " } # 设置目标时间 set_target() { # 临时保存当前缓冲区状态 temp_buffer=$(mktemp) cat $back_buffer > $temp_buffer # 显示输入提示 draw_to_back_buffer "请输入年份 (YYYY): " swap_buffers # 修复输入错误 stty -echo # 关闭回显,避免输入显示在菜单上 read target_year stty echo # 恢复回显 draw_to_back_buffer "请输入月份 (1-12): " swap_buffers stty -echo read target_month stty echo draw_to_back_buffer "请输入日期 (1-31): " swap_buffers stty -echo read target_day stty echo draw_to_back_buffer "请输入小时 (0-23): " swap_buffers stty -echo read target_hour stty echo draw_to_back_buffer "请输入分钟 (0-59): " swap_buffers stty -echo read target_minute stty echo draw_to_back_buffer "请输入秒数 (0-59): " swap_buffers stty -echo read target_second stty echo # 验证输入 valid=true case $target_year in [0-9][0-9][0-9][0-9]) ;; *) draw_to_back_buffer "错误: 年份必须是4位数字"; valid=false ;; esac case $target_month in 0[1-9]|1[0-2]|[1-9]) ;; *) draw_to_back_buffer "错误: 月份必须是1-12"; valid=false ;; esac case $target_day in 0[1-9]|[12][0-9]|3[01]|[1-9]) ;; *) draw_to_back_buffer "错误: 日期必须是1-31"; valid=false ;; esac case $target_hour in [01][0-9]|2[0-3]|[0-9]) ;; *) draw_to_back_buffer "错误: 小时必须是0-23"; valid=false ;; esac case $target_minute in [0-5][0-9]|[0-9]) ;; *) draw_to_back_buffer "错误: 分钟必须是0-59"; valid=false ;; esac case $target_second in [0-5][0-9]|[0-9]) ;; *) draw_to_back_buffer "错误: 秒数必须是0-59"; valid=false ;; esac if [ $valid = true ]; then # 计算剩余时间 if calculate_remaining; then if [ $remaining_seconds -le 0 ]; then draw_to_back_buffer "错误: 目标时间已过去!" else draw_to_back_buffer "目标时间已设置!" last_update=$(date +%s) fi fi fi swap_buffers sleep 1 # 恢复菜单状态 cat $temp_buffer > $back_buffer rm -f $temp_buffer } # 主程序入口 main() { # 初始化双缓冲系统 init_double_buffer # 初始构建菜单 build_menu swap_buffers # 主循环 while true; do # 更新剩余时间 update_remaining refresh_needed=$? # 检查是否需要刷新显示 if [ $refresh_needed -lt 2 ]; then build_menu swap_buffers fi # 修复输入错误:使用替代方法避免系统调用中断 # 尝试读取输入,忽略可能的错误 if read -t 0.1 -n 1 choice 2>/dev/null; then # 处理用户选择 case $choice in 1) set_target # 重建菜单 build_menu swap_buffers ;; 2) if [ $target_year -eq 0 ]; then draw_to_back_buffer "请先设置目标时间!" swap_buffers sleep 1 elif [ $is_running = true ]; then draw_to_back_buffer "倒计时已在运行中!" swap_buffers sleep 1 else is_running=true is_paused=false last_update=$(date +%s) draw_to_back_buffer "倒计时已开始!" swap_buffers sleep 0.5 fi # 重建菜单 build_menu swap_buffers ;; 3) if [ $is_running = true ]; then is_paused=$([ "$is_paused" = true ] && echo false || echo true) draw_to_back_buffer "已${is_paused:+"暂停":"继续"}" swap_buffers sleep 0.5 else draw_to_back_buffer "倒计时未运行!" swap_buffers sleep 0.5 fi # 重建菜单 build_menu swap_buffers ;; 4) target_year=0 target_month=0 target_day=0 target_hour=0 target_minute=0 target_second=0 remaining_seconds=0 is_running=false is_paused=true draw_to_back_buffer "已重置倒计时" swap_buffers sleep 0.5 # 重建菜单 build_menu swap_buffers ;; 5) cleanup echo "退出程序" exit 0 ;; *) draw_to_back_buffer "无效选择,请重新输入" swap_buffers sleep 0.5 # 重建菜单 build_menu swap_buffers ;; esac fi # 添加短暂延迟,减少CPU使用率 sleep 0.1 done } # 启动主程序 main 在测试过程中又出现新的问题了,输入所有菜单数字选项包括年月日都不显示数字
最新发布
08-17
#include "Menu.h" #include "dczloco.h" #include "loco.h" void Menu::openMenu() { if (!display) return; update = false; menu_page = MENU_SETTINGS; sub_page = -1; selected_item = 0; showSettings(sub_page); highlightItem(selected_item); is_menu = true; } bool Menu::isMenu() const { return is_menu; } void Menu::closeMenu() { if (!display) return; if (menu_page > MENU_SETTINGS) { showLast(); return; } clearAll(); update = true; display->setFont(u8g2_font_crox2hb_tf);//菜单返回低 updateInfo(); if (always_new) { showListening(); } else showSelectedLBJ(0); menu_page = MENU_CLOSED; sub_page = 0; is_menu = false; } void Menu::handleKey(bool up) { if (!display) return; if (!is_menu) return; if (is_msg) return; switch (menu_page) { case MENU_CLOSED: break; case MENU_SETTINGS: if (up) selected_item--; else selected_item++; if (selected_item < 0) { sub_page--; selected_item = 3; } if (selected_item > 3) { sub_page++; selected_item = 0; } if (sub_page > -1) { sub_page = -1; /*if (always_new) { sub_page = -1;//页数 } else { menu_page = MENU_RX_INFO; sub_page = -1; //showInfo((int8_t) sub_page); break; }*/ } if (sub_page < -1)//页数 sub_page = -1; showSettings(sub_page); highlightItem(selected_item); break; case MENU_ABOUT: if (up) sub_page--; else sub_page++; if (sub_page < 1) sub_page = 1; if (sub_page > 1) sub_page = 1; showAbout(sub_page); break; case MENU_Buzzer: break; case MENU_OLED: break; case MENU_Bzz: break; case MENU_LCDA: break; } } void Menu::showSettings(int16_t page) { if (!display) return; clearAll(); display->setFont(u8g2_font_wqy16_t_gb2312); display->drawUTF8(96, 16, "系统设置"); display->drawHLine(0, 20, 256); switch (page) { case -1: { items[0] = "蜂鸣器开关";//蜂鸣器 items[1] = "震动开关";//震动 items[2] = "背光灯开关";//背光灯 items[3] = "关于";//关于 for (int i = 0, c = 38; i < 4; ++i, c += 18) { display->drawUTF8(0, c, items[i].c_str()); } break; } default: break; } } void Menu::highlightItem(int8_t item) { display->drawBox(0, 23 + item * 18, 256, 18); display->setDrawColor(0); display->drawUTF8(0, 38 + item * 18, items[item].c_str()); display->setDrawColor(1); display->sendBuffer(); } void Menu::acknowledge() { if (!display) return; if (is_msg) { showLast(); return; } switch (menu_page) { case MENU_SETTINGS: if (sub_page == -1) { switch (selected_item) { case 0: menu_page = MENU_Buzzer;//蜂鸣器 showBuzzer(); selected_item = 0; highlightItem(selected_item); break; case 1: menu_page = MENU_Bzz;//震动 showBzz(); selected_item = 0; highlightItem(selected_item); break; case 2: menu_page = MENU_LCDA;//背光灯 showLCDA(); selected_item = 0; highlightItem(selected_item); break; case 3: menu_page = MENU_ABOUT;//关于 sub_page = 1; showAbout(1); break; default: break; } } break; case MENU_Buzzer://蜂鸣器 if (bz_buzzer ) { prb_count = 0; prb_timer = 0; car_count = 0; car_timer = 0; bz_buzzer = false; showBuzzer(); pinMode(beep_pin, OUTPUT);//pinMode(beep_pin, INPUT); highlightItem(selected_item); } else { bz_buzzer = true; showBuzzer(); pinMode(beep_pin, INPUT);//pinMode(beep_pin, OUTPUT); highlightItem(selected_item); } break; case MENU_Bzz://震动 if (bz_bzz ) { prb_count = 0; prb_timer = 0; car_count = 0; car_timer = 0; bz_bzz = false; showBzz(); pinMode(BOARD_LED, INPUT); highlightItem(selected_item); } else { bz_bzz = true; showBzz(); pinMode(BOARD_LED, OUTPUT); highlightItem(selected_item); } break; case MENU_LCDA://背光灯 if (bz_LCDA ) { prb_count = 0; prb_timer = 0; car_count = 0; car_timer = 0; bz_LCDA = false; showLCDA(); pinMode(LEDA_PIN, INPUT); highlightItem(selected_item); } else { bz_LCDA = true; showLCDA(); pinMode(LEDA_PIN, OUTPUT); highlightItem(selected_item); } break; break; default: return; } } void Menu::showLast() { if (is_msg) is_msg = false; switch (menu_page) { case MENU_Buzzer://蜂鸣器 sub_page = -1;//第1页 showSettings(sub_page); selected_item = 0;//第一项 highlightItem(selected_item); menu_page = MENU_SETTINGS; break; default: case MENU_Bzz://震动 sub_page = -1;//第1页 showSettings(sub_page); selected_item = 1;//第2项 highlightItem(selected_item); menu_page = MENU_SETTINGS; break; case MENU_LCDA://背光灯 sub_page = -1;//第1页 showSettings(sub_page); selected_item = 2;//第3项 highlightItem(selected_item); menu_page = MENU_SETTINGS; break; case MENU_ABOUT://关于 sub_page = -1;//第1页 showSettings(sub_page); selected_item = 3;//第4项 highlightItem(selected_item); menu_page = MENU_SETTINGS; break; return; } } void Menu::showAbout(int16_t page) { clearAll(); display->setFont(u8g2_font_wqy16_t_gb2312); display->drawUTF8(112, 14, "关于"); display->drawHLine(0, 18, 256); //display->drawUTF8(118, 12, String(page).c_str()); char buffer[32]; if (page == 1) { } display->sendBuffer(); } void Menu::showMessage(const char *title, const char *message) { is_msg = true; display->setFont(FONT_12_GB2312); display->setDrawColor(0); display->drawBox(12, 4, 104, 58); display->setDrawColor(1); display->drawFrame(12, 4, 104, 58); display->drawUTF8(15, 16, title); display->drawHLine(14, 18, 100); pwordUTF8(String(message), 18, 34, 100, 58); display->sendBuffer(); } void Menu::updatePage() { if (!is_menu) return; if (millis64() - update_timer < 30) return; switch (menu_page) { case MENU_FREQ: //showFreq(); highlightItem(selected_item); break; case MENU_TF_SETTINGS: if (sub_page != 1) return; //showTFSettings(sub_page); highlightItem(selected_item); break; default: return; } update_timer = millis64(); } void Menu::showBuzzer(bool send) { clearAll(); // display->setDrawColor(0); // display->drawBox(0,0,128,64); // display->setDrawColor(1); display->setFont(u8g2_font_wqy16_t_gb2312); display->drawUTF8(0, 14, "蜂鸣器"); display->drawHLine(0, 18, 256); items[0] = "蜂鸣器开关 "; if (bz_buzzer ) items[0] += "[已关闭]";//已开启 else items[0] += "[已开启]";//已关闭 if (send) display->sendBuffer(); } void Menu::showBzz(bool send) { clearAll(); display->setFont(u8g2_font_wqy16_t_gb2312); display->drawUTF8(0, 14, "震动"); display->drawHLine(0, 18, 256); items[0] = "震动开关 "; if (bz_bzz ) items[0] += "[已开启]"; else items[0] += "[已关闭]"; if (send) display->sendBuffer(); } void Menu::showLCDA(bool send) { clearAll(); display->setFont(u8g2_font_wqy16_t_gb2312); display->drawUTF8(0, 14, "背光灯"); display->drawHLine(0, 18, 256); items[0] = "背光灯 "; if (bz_LCDA ) items[0] += "[已开启]"; else items[0] += "[已关闭]"; if (send) display->sendBuffer(); } 这个一个菜单的代码,但是我想修改一下,添加一个可以修改RTC时间的菜单,已经有RTC初始化的程序了,用的#include <RTClib.h>库,
07-22
可结合迅闪,网维大师等任意的三层更新软件使用的菜单。免费漂亮的游戏菜单。 2010年,网吧无盘游戏菜单到底用哪个好?这里我们只讨论无盘客户机的游戏菜单,不考虑无盘服务器上的游戏三层更新软件,一般的三层更新软件都带有了客户机的游戏菜单,但这些菜单一般是有广告,或者收费的形式存在的,他们的菜单体积庞大,并没有针对无盘的特殊环境进行特殊的优化,所以不仅体积大,广告多,而且资源占用严重,因为他们把许多有盘上才用得着的功能全放在无盘上去用了。下面就推荐一款无盘上客户机专用的游戏菜单2010版: 你是否正在使用无盘系统并寻找一款专门用在无盘上的游戏菜单你是否正在寻找一款单机游戏菜单?你是否需要自己一个印有个人姓名或者公司名称和链接的OEM游戏菜单?你是否在寻找一个简单可依赖的游戏菜单?你是否正在寻找一个漂亮的游戏菜单?你是否需要一个家庭版的游戏菜单来管理等等繁乱的桌面?你是否正在使用虚拟磁盘系统不需要繁琐的更新游戏功能?如果你符合上面一条,那么请你往下看,这里推荐一款适合你的游戏菜单 特点: ======================= 1、漂亮,美观 2、简单、实用、快速 3、免费 4、多款皮肤,并可自行制作皮肤。 5、无网络验证,可永久免费使用 6、专门为设计。无盘 7、游戏管理方便,全傻瓜式的拖拽操作即可完成游戏添加 8、自动导入游戏方便。可一键导入分类下所有游戏。 9、无局域网游戏更新功能,但可结合更新插件更新 10、支持点击率统计和排序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值