当前位置: 首页 > news >正文

Android开发,实现底部弹出菜单

文章目录

    • 1. 实现分析
        • 1. 继承 Dialog 并实现点击监听
        • 2. 视图初始化
        • 3. 窗口设置
        • 4. 点击处理
        • 5. 触摸外部关闭
    • 2. 代码实现过程
    • 3. 如何使用?
    • 4. 效果图演示

1. 实现分析

1. 继承 Dialog 并实现点击监听
  • 继承 Dialog 类并实现 View.OnClickListener
  • 使用自定义样式 R.style.option_dialog
2. 视图初始化
  • 在构造函数中加载布局 R.layout.dialog_from_custom
  • 初始化按钮视图并设置点击监听
3. 窗口设置
  • onCreate 中设置对话框显示在底部
  • 设置对话框宽度为屏幕宽度
4. 点击处理
  • 处理三个按钮的点击事件
  • 通过回调接口 OnDialogClickListener 通知外部点击事件
5. 触摸外部关闭
  • 设置窗口装饰视图的触摸监听,点击外部时关闭对话框

2. 代码实现过程

  1. 写一个DownDialog extends Dialog
public class DownDialog extends Dialog implements View.OnClickListener {private TextView btn_take_photo, btn_select_photo, btn_cancel;//构造方法里面设置主题 R.style.option_dialogpublic DownDialog(Context context) {this(context, R.style.option_dialog);}public DownDialog(Context context, int themeResId) {super(context, themeResId);//加载布局文件View view = LayoutInflater.from(context).inflate(R.layout.dialog_from_custom, null);initView(view);initListener();setContentView(view);getWindow().getDecorView().setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {dismiss();return true;}});}private void initListener() {btn_cancel.setOnClickListener(this);btn_take_photo.setOnClickListener(this);btn_select_photo.setOnClickListener(this);}private void initView(View view) {btn_take_photo = view.findViewById(R.id.btn_take_photo);btn_select_photo = view.findViewById(R.id.btn_select_photo);btn_cancel = view.findViewById(R.id.btn_cancel);}@SuppressWarnings("deprecation")@Overrideprotected void onCreate(Bundle bundle) {super.onCreate(bundle);getWindow().setGravity(Gravity.BOTTOM);WindowManager m = getWindow().getWindowManager();Display d = m.getDefaultDisplay();WindowManager.LayoutParams p = getWindow().getAttributes();p.width = d.getWidth();getWindow().setAttributes(p);}@Overridepublic void onClick(View v) {if (v.getId() == R.id.btn_take_photo) {if (onDialogClickListener != null) {onDialogClickListener.onDialogClick("拍照", 1);}} else if (v.getId() == R.id.btn_select_photo) {if (onDialogClickListener != null) {onDialogClickListener.onDialogClick("相册", 2);}} else {if (onDialogClickListener != null) {onDialogClickListener.onDialogClick("取消", 3);}}dismiss();}//回调public interface OnDialogClickListener {void onDialogClick(String msg, int type);}private OnDialogClickListener onDialogClickListener;public void setOnDialogClickListener(OnDialogClickListener onDialogClickListener) {this.onDialogClickListener = onDialogClickListener;}}
  1. 在res/values/themes.xml 定义 样式主题option_dialog
    <style name="option_dialog" parent="@style/dialog_common"><item name="android:windowAnimationStyle">@style/AnimBottom</item><item name="android:windowBackground">@color/me_background_color</item></style><style name="dialog_common" parent="Base.AlertDialog.AppCompat.Light"><item name="android:windowBackground">@color/me_background_color</item></style><style name="AnimBottom" parent="@android:style/Animation"><item name="android:windowEnterAnimation">@anim/push_bottom_in</item><item name="android:windowExitAnimation">@anim/push_bottom_out</item></style>
  1. 在res/values/colors.xml中 定义me_background_color颜色
     <color name="base_start_color_gray">#e8e9eb</color><color name="me_background_color">#b0000000</color><color name="base_start_color_pressed">#fffcfcfc</color><color name="base_end_color_pressed">#ffd7d7d7</color><color name="base_start_color_default">#FFFFFF</color><color name="base_end_color_default">#FFFFFF</color>
  1. 在res/anim 中定义push_bottom_inpush_bottom_out动画 (如果没有anim ,先创建)

push_bottom_in.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- 上下滑入式 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" ><translateandroid:duration="200"android:fromYDelta="50%p"android:toYDelta="0" /></set>

push_bottom_out.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- 上下滑入式 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" ><translateandroid:duration="200"android:fromYDelta="0"android:toYDelta="50%p" /></set>
  1. dialog_from_custom.xml 布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/pop_layout"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_horizontal"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_marginLeft="15dp"android:layout_marginRight="15dp"android:gravity="center_horizontal"android:orientation="vertical"><TextViewandroid:id="@+id/btn_take_photo"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:gravity="center"android:background="@drawable/background_view_rounded_top"android:paddingBottom="8dp"android:paddingTop="8dp"android:text="拍照"android:textColor="#282828"android:textSize="16sp" /><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:background="#dddddd" /><TextViewandroid:id="@+id/btn_select_photo"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/background_view_rounded_bottom"android:paddingBottom="8dp"android:paddingTop="8dp"android:text="相册选取"android:gravity="center"android:textColor="#282828"android:textSize="16sp" /><TextViewandroid:id="@+id/btn_cancel"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_marginBottom="10dip"android:layout_marginTop="8dip"android:background="@drawable/rect_gray"android:paddingBottom="8dp"android:gravity="center"android:paddingTop="8dp"android:text="取消"android:textColor="#282828"android:textSize="16sp" /></LinearLayout>
</RelativeLayout>
  1. 在res/drawable下分别创建background_view_rounded_top.xmlbackground_view_rounded_bottom.xmlrect_gray.xml

background_view_rounded_top.xml

<?xml version="1.0" encoding="UTF-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"android:insetLeft="1.0px"android:insetRight="1.0px"><selector><item android:state_pressed="true"><shape><gradientandroid:angle="270.0"android:endColor="@color/base_end_color_pressed"android:startColor="@color/base_start_color_pressed" /><cornersandroid:topLeftRadius="6dp"android:topRightRadius="6dp" /></shape></item><item><shape><gradientandroid:angle="270.0"android:endColor="@color/base_end_color_default"android:startColor="@color/base_start_color_default" /><cornersandroid:topLeftRadius="6dip"android:topRightRadius="6dip" /></shape></item></selector></inset>

background_view_rounded_bottom.xml

<?xml version="1.0" encoding="UTF-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"android:insetLeft="1.0px"android:insetRight="1.0px"><selector><item android:state_pressed="true"><shape><gradientandroid:angle="270.0"android:endColor="@color/base_end_color_pressed"android:startColor="@color/base_start_color_pressed" /><cornersandroid:bottomLeftRadius="6dip"android:bottomRightRadius="6dip"/></shape></item><item><shape><gradientandroid:angle="270.0"android:endColor="@color/base_end_color_default"android:startColor="@color/base_start_color_default" /><cornersandroid:bottomLeftRadius="6dip"android:bottomRightRadius="6dip"/></shape></item></selector>
</inset>

rect_gray.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><!-- 填充颜色 --><solid android:color="#FFFFFF"/><!-- 线的宽度,颜色灰色 --><!--<stroke--><!--android:width="1dp"--><!--android:color="#fffcfcfc"/>--><!-- 矩形的圆角半径 --><corners android:radius="6dp" />
</shape>

3. 如何使用?

DownDialog downDialog = new DownDialog(MainActivity.this);
downDialog.setOnDialogClickListener(new DownDialog.OnDialogClickListener() {@Overridepublic void onDialogClick(String msg, int type) {switch (type) {case 1: // 拍照Toast.makeText(MainActivity.this, "点击了拍照", Toast.LENGTH_SHORT).show();break;case 2: // 相册Toast.makeText(MainActivity.this, "点击了相册", Toast.LENGTH_SHORT).show();break;case 3: // 取消Toast.makeText(MainActivity.this, "点击了取消", Toast.LENGTH_SHORT).show();break;}}
});
downDialog.show();

4. 效果图演示

在这里插入图片描述

http://www.xdnf.cn/news/132535.html

相关文章:

  • GStreamer 简明教程(十一):插件开发,以一个音频生成(Audio Source)插件为例
  • ‌Linux trap 命令详解
  • report builder问题
  • springboot3 声明式 HTTP 接口
  • JUC多线程:读写锁
  • 【高频考点精讲】前端构建工具对比:Webpack、Vite、Rollup和Parcel
  • 淘宝 /天猫/1688|京东API 常用接口列表与申请方式解析
  • P12167 [蓝桥杯 2025 省 C/Python A] 倒水
  • 对接金蝶获取接口授权代码
  • 第3讲、大模型如何理解和表示单词:词嵌入向量原理详解
  • Blender好用的插件推荐汇总
  • 电脑温度怎么看 查看CPU温度的方法
  • Golang | 位运算
  • DELPHI实现dbTreeView的节点拖动并更新
  • 为什么说美颜SDK动态贴纸才是直播、短视频平台的下一个爆点?看完你就懂了!
  • 连续帧点云目标检测结果展示,python实现
  • 这个免费的AI插件,居然让我5分钟看完2小时的YouTube视频!
  • 大麦项目pro版本来袭!扫平面试中的一切疑难杂症!
  • 视频丨Google 最新 AI 眼镜原型曝光:轻量 XR+情境感知 AI 打造下一代计算平台
  • 【C语言练习】002. 理解C语言的基本语法结构
  • 存储新势力:助力DeepSeek一体机
  • GIT下载步骤
  • Base64编码原理:二进制数据与文本的转换技术
  • 因泰立H13激光雷达赋能垃圾发电厂,炉渣体积测量与装车智能化
  • 跨Linux发行版CPU指令集兼容性深度解析与实践指南
  • 一文读懂Nginx应用之 CentOS安装部署Nginx服务
  • 当智驾成标配,车企暗战升级|2025上海车展
  • 告别 “幻觉” 回答:RAG 中知识库与生成模型的 7 种对齐策略
  • CUDA编程之Grid、Block、Thread线程模型
  • 用 ESP32 模拟 Wiegand 刷卡器:开发门禁系统必备的小工具