Android使用PopupWindow高仿iOS Messages录音弹出界面

Android使用PopupWindow高仿iOS Messages录音弹出界面

通过前面几回开发,已经完成录音界面所需的界面元素。

过程 描述
Android实现录音功能汇总 比较了MediaRecorderAudioRecord的功能,并选择MediaRecorder作为实现方案。
Android低仿iOS Messages录音波形效果 实现了录音的波形效果。
Android高仿iOS Messages声音播放波形效果 实现了播放录音的波形效果。
Android高仿iOS Messages录音操作按钮 实现了录音操作按钮。

接下来,选择合适的容器将所有的功能元素组织到一起。

一、目标

使用PopupWindow将所有录音界面元素组织到一起。

继续推进神马笔记录音编辑器开发。

红色透明部分为PopupWindow的Content View。

二、功能分析

截图 描述
初始状态
长按录音按钮,开始录音。
自动隐藏文字输入栏。
显示第三方扩展。
录音停止按钮与波形条是垂直居中的。
文字编辑栏不可见。
按下录音操作按钮以外的区域,包括键盘区自动取消录音。
显示软键盘和第三方扩展。

三、方案选择

我们的目标是长按之后,弹出一个界面,并且弹出的界面能继续处理Touch事件。

可选方案 说明
Dialog 使用Dialog弹出界面最为简单,但会同时隐藏软键盘。
我们希望同时保留软键盘,因此不适用。
FrameLayout 使用FrameLayout作为容器,将弹出界面添加到FrameLayout最上层。
用户依然可以操作键盘区域,同样不适用。
PopupWindow 完美符合要求。

四、参考文章

文章 说明
Android弹窗_PopupWindow详解 非常详尽地介绍了PopupWindow的功能。

五、系统相关类

系统中使用到PopupWindow的类。

说明
ListPopupWindow PopupMenu和AutoCompleteTextView通过ListPopupWindow间接使用了PopupWindow。
KeyboardView 实现长按软键盘弹出界面。

六、开源项目

当前的需求比较简单,还没有参考开源项目,已经实现目标功能。

PopFisher / SmartPopupWindow 提供关于PopupWindow使用过程中遇到的一些特殊问题的解决方案,例如:PopupWindow不响应点击外部消失和返回键消失的解决方法;PopupWindow精确计算要显示位置原理和方法;实现带箭头的上下文菜单遇到的坑;Android7.0 PopupWindow的兼容问题;屏幕旋转时调用PopupWindow update方法更新位置失效的问题及解决方案
li-xiaojun / XPopup 🔥功能强大,UI简洁,交互优雅的通用弹窗!可以替代Dialog,PopupWindow,PopupMenu,BottomSheet,DrawerLayout,Spinner等组件,自带十几种效果良好的动画, 支持完全的UI和动画自定义!(Powerful and Beautiful Popup,can absolutely replace Dialog,PopupWindow,PopupMenu,…
zyyoona7 / EasyPopup PopupWindow Wrapper. 对 PopupWindow 的封装。可指定相对于 anchor view 各个方位弹出,设置背景变暗,指定 ViewGroup 背景变暗等特性。
kakajika / RelativePopupWindow Android PopupWindow that can be easily located relative to anchor View.
pinguo-zhouwei / CustomPopwindow 对PopupWindow常用API的简单封装,几行代码就搞定PopupWindow弹窗,使用Builder模式,链式调用,像使用AlertDialog 一样
douglasjunior / android-simple-tooltip A simple library based on PopupWindow to create Tooltips on Android. 💚
kyleduo / BlurPopupWindow PopupWindow with blurred background.
minetsh / PopupMenuView A view just like UIMenuController of iOS, 一个类似iOS中弹框气泡菜单的控件
shangmingchao / PopupList The edit menu in Android, like the UIMenuController in iOS

七、一些相关技术点

1. PopupWindow的尺寸

这里使用了MATCH_PARENT,然后通过设置容器的padding或者margin进行定位。

使用WRAP_CONTENT,然后showAtLocation时,调整位置同样可以达成目标。

数值 含义
WRAP_CONTENT 内容自适应
MATCH_PARENT 充满整个屏幕
指定尺寸 用户指定尺寸

2. 计算软键盘的高度

通过获取整个屏幕高度,扣除掉DecorView的矩形底部,计算出软键盘高度。

1
2
3
4
5
6
7
8
9
DisplayMetrics dm = new DisplayMetrics();
Display d = parent.getWindowManager().getDefaultDisplay();
d.getMetrics(dm);
int visibleHeight = dm.heightPixels;

final Rect visibleDisplayFrame = new Rect();
anchor.getRootView().getWindowVisibleDisplayFrame(visibleDisplayFrame);

int height = (visibleHeight - visibleDisplayFrame.bottom);

3. 处理touch事件

我们希望长按弹出界面后,弹出界面可以继续处理touch事件。

重载ActivitydispatchTouchEvent()方法,将事件传递到弹出界面。

1
2
3
4
5
6
7
8
9
10
11
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean result = super.dispatchTouchEvent(ev);

tapeHelper.setTouchEvent(ev);
if (tapeHelper.interceptTouchEvent) {
tapeHelper.dispatchTouchEvent();
}

return result;
}

八、开发过程回顾

  1. 分析功能需求
  2. 比较3种实现方案,Dialog、FrameLayout、PopupWindow
  3. 选定PopupWindow作为实现方案
  4. 解决PopupWindow尺寸问题,采用全屏方式,通过padding和margin定位子控件
  5. 解决软键盘高度问题,实现弹出软键盘时定位问题
  6. 解决touch事件,保证弹出界面能继续处理事件

九、接下来

经过5个开发过程,录音相关的所有技术问题都得到解决。

接下来整合所有的功能点,完成神马笔记的录音编辑器。

十、Finally

须菩提。 若菩萨作是言。 我当庄严佛土。是不名菩萨。