当前位置: 首页 > 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. 效果图演示

在这里插入图片描述

相关文章:

  • 高等数学第二章---导数与微分(2.1~2.3)
  • 求职意向商务/BD简历模板
  • 通讯的基础概念:涵盖串行通信、并行通信、TCP、UDP、Socket 等关键概念和技术
  • [AI Workflow] 基于多语种知识库的 Dify Workflow 构建与优化实践
  • 统计术语学习
  • 零信任架构:重塑网络安全的IT新范式
  • AI与思维模型【76】——SWOT思维模型
  • PyTorch生成式人工智能实战(3)——分类任务详解
  • Unity3D Lua集成技术指南
  • 含锡废水处理的经济效益
  • Android APP 热修复原理
  • java.lang.ArrayIndexOutOfBoundsException: 11
  • 时间序列预测模型比较分析:SARIMAX、RNN、LSTM、Prophet 及 Transformer
  • 51单片机中断
  • Electron从入门到入门
  • Nacos简介—2.Nacos的原理简介
  • Linux:进程间通信->匿名管道实现内存池
  • 深入剖析 Vue 双向数据绑定机制 —— 从响应式原理到 v-model 实现全解析
  • Android中的多线程
  • ubuntu20.04安装x11vnc远程桌面
  • 贵州通报9起群众身边不正之风和腐败问题典型案例
  • 美联储报告披露关税战冲击波:消费信心下降,经济担忧加深
  • 科克托是说真话的骗子,而毕加索是一言不发、让大家去猜的人
  • “今日海上”对话“今日维也纳”,东西方艺术在上海碰撞
  • 官宣一起打造智能汽车品牌后,华为喊话上汽要准备好足够产能
  • 印控克什米尔发生恐袭事件,外交部:中方反对一切形式的恐怖主义