高仿iOS的BlurDialog
2016-03-03 16:52
453 查看
文/BlackSwift(简书作者)
原文链接:http://www.jianshu.com/p/1e2d68183c3c
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
本文主要讨论Dialog的blur背景与泛谈window中的各种view。
Github上有许多仿iOS的dialog,但是都没有让背景模糊,第三方的view太坑,不如自己对着iOS模拟器的图与动画做出来。耗费了很久时间终于搞定了,如下图,左边是仿iOS的dialog,右边是SupportV7的dialog。
BlurDialog
当调用
当调用
如果我们需要自定义一个dialog,只需要在
在
模糊效果可以参考我之前写的
BlurDrawable
注意不能用系统自带的dialog,因为它的内部是不开放的(也就是红色的代码),window创建流程也不透明,可能会抛出异常。
本部分完,需要ui的直接clone即可。
以下为冗长的理论资料
WindowManager是系统服务,负责view绘制。它对开发中看来也只是一个接口,通过
接口由ROM实现
反编译jar后,可以获得对象
在国产ROM常见的状态栏字体变色,悬浮Activity等特色功能,都是由
通过 Dump 工具可以验证:
Dump
网上有部分文章说
举个例子,在最新的 AppCompatActivity 中,它重写的
contentView可以通过ID获得,这个id是内置的,如下两个是等价的
如果view本身需要被add时(比如dialog,activity),调用
如果这个view并没有parent(比如viewholder), 选择不依附即可
涉及到长宽等内容时,因为view的显示是异步的,所以需要post发送,以免获得到的结果为0
原文链接:http://www.jianshu.com/p/1e2d68183c3c
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
本文主要讨论Dialog的blur背景与泛谈window中的各种view。
Github上有许多仿iOS的dialog,但是都没有让背景模糊,第三方的view太坑,不如自己对着iOS模拟器的图与动画做出来。耗费了很久时间终于搞定了,如下图,左边是仿iOS的dialog,右边是SupportV7的dialog。
BlurDialog
Dialog 生命周期的简要分析
在构造函数时,创建了一个window,并设置了相关window属性。当调用
show()时,首先调用了
onCreate与
onStart(都是一些无关紧要的方法),最后通过
WindowManager添加了 window 中的 DecoView,从这里开始,view就要开始走绘制流程了。
当调用
dismiss()时,通过
WindowManager移除了 View,并调用
onStop()执行可能的清理任务。
@see #Dialog (setUp window inside) @see #show() - @see #onCreate(Bundle) (call setContentView here) - @see #onStart() - mWindowManager.addView(mDecor, l); @see #dismiss() - mWindowManager.removeViewImmediate(mDecor); - @see #onStop() (clean work)
如果我们需要自定义一个dialog,只需要在
show()之前配置好 window 的属性,以及在
onCreate()中将自定义的 xml 布局初始化即可。
在
mWindowManager.addview()之前,除非指定了 view 的dp高宽,否则输出的view高度等数据将是0,-1之类的值。为了获得准确的值,可以使用
view.post()将消息入队,这样可以获取到正确的数据。
BlurAlertDialog 的实现
通过post入队即可,入队主要是为了准确测量偏移量。//初始化 BlurDrawable 的样式 //`mRvFragCard`表示在底层的将要被模糊的View BlurDrawable drawable = new BlurDrawable(mRvFragCard); dialog.getWindow().getDecorView().post(new Runnable() { @Override public void run() { //设置边缘圆弧的 dp drawable.setCornerRadius(xxDp); // 设置绘制偏移量 // 坐标为相对整个屏幕,dialog最左边,最上面的点 drawable.setDrawOffset(x,y); dialog.getWindow().setBackgroundDrawable(drawable); } }); dialog.show();
模糊效果可以参考我之前写的
BlurDrawable
注意不能用系统自带的dialog,因为它的内部是不开放的(也就是红色的代码),window创建流程也不透明,可能会抛出异常。
示例地址
本文项目本部分完,需要ui的直接clone即可。
以下为冗长的理论资料
Window 与 WindowManager
window是对整个view的一套管理,对开发者来说仅仅是接口。PhoneWindow是对
window的抽象方法的实现,手机ROM厂商可以修改或者实现它,而开发者只能反射调用
PhoneWindow的一些功能。
WindowManager是系统服务,负责view绘制。它对开发中看来也只是一个接口,通过
getSystemService即可获得。
接口由ROM实现
/system/framework/framework.jar
反编译jar后,可以获得对象
android.view.WindowManagerGlobal,具体流程可以看这里,我们只需要知道这个函数涉及到AIDL通信,并且它是异步回调的即可。
在国产ROM常见的状态栏字体变色,悬浮Activity等特色功能,都是由
WindowManager负责绘制的,通过在 Window 中写入某些flag,之后重绘的时候就能显示出独有的样式。
Dialog 下的 Window 布局
此场景适用于最原始的 Activity 与 Dialog ,它们的 ViewTree 布局如下DecoView DecorContentParent ContentView(android.R.id.content) 你写的xml布局
通过 Dump 工具可以验证:
Dump
1. DecoView
在PhoneWindow中,它的变量名为
mDecor, 它是 window 中的 top-level 的view,通过
installDecor()进行构造,它默认的大小是
wrap_content,我们通常所说的
window.setXXX()本质上调用的就是 DecoView(与它的子view)
网上有部分文章说
DecoView不是top-level 的 View,这个说法是错的,各位可以手动设置 id 测试
2. DecorContentParent
在PhoneWindow中,它的变量名为
mDecorContentParent,通过它可以设置
Window中的Title,
requestWindowFeature等功能,它是一个宽泛的层,层次可能是一层(在NoActionBar,notitle的条件下),可能有多个层,上图就有3层。在实际开发中,我们一般也用不到(如果非要用的话,还是只能反射调用)。
举个例子,在最新的 AppCompatActivity 中,它重写的
setContentView中通过
ensureSubDecor()方法手动填充几个夹层View,这个算一个应用案例
@Override public void setContentView(int resId) { //对mWindow.setContentView()的一道包装 //添加部分View, 比如Actionbar/Title/Toolbar ensureSubDecor(); ..... }
3. ContentView
在PhoneWindow中,它的变量名为
mContentParent。我们日常接触的就是
ContentView了,它包装着我们写的xml布局
contentView可以通过ID获得,这个id是内置的,如下两个是等价的
android.R.id.contentWindow.ID_ANDROID_CONTENT
4. xml布局
我们自己写的xml布局,需要注意 inflate 方法中的boolean值,它控制当前view是否依附到 parent 中。如果view本身需要被add时(比如dialog,activity),调用
setContentView()即可,它将生成view并依附到parent中。
如果这个view并没有parent(比如viewholder), 选择不依附即可
inflater.inflate(ResId, null, false);
总结
尽量在setcontentView之前调用window属性涉及到长宽等内容时,因为view的显示是异步的,所以需要post发送,以免获得到的结果为0
相关文章推荐
- podofo在ios下config文件无错配置
- iOS打电话功能
- iOS开发之信用卡 扫描识别卡号信息(card.io)
- iOS本地通知
- iOS开发对于第三方类库的管理-cocoapods
- IOS 渲染过程
- 手动集成google map iOS sdk
- 利用AVPlayer播放iOS沙盒中的视频
- iOS中时间格式的转化(NSString/NSDate)
- iOS中NSlog重定向到文件
- ios 支付宝使用
- iOS字体相关知识
- IOS开发选择图片(相机或者图库)
- iOS开发-进阶:JSPatch 实现原理详解
- 欢迎使用CSDN-markdown编辑器
- iOS沙盒与文件管理
- iOS开发-BUG:证书显示 此证书签发者无效 解决办法
- iOS开发 校验身份证号码真伪
- iOS开发---切换日历的月份/星期/年
- iOS Failed to find matching arch for 64-bit Mach-O input file