导航:首页 > 操作系统 > androidview顶层

androidview顶层

发布时间:2024-02-02 01:34:46

1. android 怎么实现一个view悬浮到recyclerview上层

可以使用
layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
防止item 交换位置

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
layoutManager.invalidateSpanAssignments(); //防止第一行到顶部有空白区域
}

2. android 如何获取一个界面最顶层的view并处理单击事件的分发机制

android事件分发机制 就是一个触摸事件发生了,从一个窗口传递到一个视图,再传递到另外一个视图,最后被消费的过程,在android中还是比较复杂的传递流程如下:

(1) 事件从Activity.dispatchTouchEvent()开始传递,只要没有被停止或拦截,从最上层的View(ViewGroup)开始一直往下(子View)传递。子View可以通过onTouchEvent()对事件进行处理。

(2) 事件由父View(ViewGroup)传递给子View,ViewGroup可以通过onInterceptTouchEvent()对事件做拦截,停止其往下传递。

3. 安卓视图层级大揭秘

最近接了一个语音控制的功能,UI上的具体实现就是在应用上遮盖一个透明防触层,在语音状态下阻止用户点击,但不能影响物理返回键的Dialog呼出即控制,同时对于非物理返回键呼出的Dialog也要阻止操作。功能看起来很绕,我们用一张图片来具体说明一下。

通过图片不难看出,我们要实现的语音控制层其实是介于应用视图与视图内部提示框之上,同时又在Back返回键弹窗之下的一个层级。因为一直以来对安卓视图层级的探究不是很深入,所以借着做这个功能对安卓视图层级这一块的知识进行了一下总结梳理。

首先让我们通过一张层级图来明确几个重要的概念Window,DecorView和mContentParent。

在Android中不管是Activity、Toast、ActionBar还是Dialog,他们的视图都是附加到Window上,其实基本上所有的view同时通过Window来呈现的,因此Window可以理解为是view的承载者和管理者。Window 有三种类型,分别是应用 Window、子 Window 和系统 Window。应用类 Window 对应一个 Acitivity,子 Window 不能单独存在,需要依附在特定的父 Window 中,比如常见的一些 Dialog 就是一个子 Window。系统 Window是需要声明权限才能创建的 Window,比如 Toast 和系统状态栏都是系统 Window。

DecorView是Windows中的View的最顶层View。其实DecorView是FrameLayout的子类,它里面包含了一个存有ActionBar以及mContentParent的LinearLayout。

mContentParent这个名字可能会有些陌生,其实他就是我们经常使用的应用根布局,即android.R.id.content。Activity中的setContentView其实就是通过LayoutInflater将XML布局转换成View并添加到mContentParent中。

每个Activity都会持有一个Window,而在安卓中,Window只有唯一的一个实现类PhoneWindow ,所以每个Activity都会持有一个PhoneWindow,在PhoneWindow中会持有顶层视图DecorView。那么Activity是怎么建立与PhoneWindow的联系的呢,让我们通过源码来探究一下:

在Activity的启动过程中会执行ActivityThread的performLaunchActivity方法,其中调用Activity的attach。在attach()方法中实例化Activity持有的mWindow。由于 Activity 实现了 Window 的 Callback 接口,因此当 Window 接受到外界的状态改变时就会回调 Activity 的方法。

可以看到,在PhoneWindow里面,出现了成员变量DecorView。而这里,DecorView则是PhoneWindow里面的一个内部类,它是继承于FrameLayout。

这是我们每次写Activity都会调用的setContentView方法,它的内部调用了getWindow()的setContentView,这个mWindow就是PhoneWindow。

我们看到在PhoneWindow中有三个setContentView的重载方法。在setContentView(int layoutResID)中,首先判断了mContentParent ,如果mContentParent 为空即为第一次调用的时候,就执行installDecor()方法,创建DecorView,并添加到mContentParent上。如果mContentParent不为空,那么将mContentParent中的view移除。接着通过mLayoutInflater将XML转换为View树,并且添加至mContentParent视图中。 添加完成后回调通知onContentChanged,表示完成界面加载。

首先判断mDecor是否为空,如果为空则通过generateDecor创建一个DecorView,紧接着设置DecorView的获取焦点能力为FOCUS_AFTER_DESCENDANTS,即先分发给Child View进行处理,如果所有的Child View都没有处理,则自己再处理。第一次DecorView未加载到mContentParent,所以mContentParent为空,调用generateLayout将setContentView内容添加到mContentParent。

定制过Acitivity的Actionbar或是Fullscreen的同学一定都知道,requesetFeature方法需要在setContentView之前调用,这就是原因。setContentView的实质显示是触发了Activity的resume状态,也就是触发了makeVisible方法。

这里将getWindow().getAttributes()作为了LayoutParams,在WindowManager中:

可以看到Activity的窗口类型是TYPE_APPLICATION,这个TYPE类型决定了在Window层的显示层级,TYPE类型总览如下:

Dialog不属于View,他是应用的子window,所以这也是为什么我们通过给mContentParent添加view无法实现遮挡Dialog的原因。Dialog 中 Window 同样是通过 PolicyManager 的 makeNewWindow 方法来完成的,普通的 Dialog 必须采用 Activity 的 Context,如果采用 Application 的 Context 就会报错。这是因为没有应用 token 导致的,而应用 token 一般只有 Activity 拥有。常规Dialog的TYPE为TYPE_APPLICATION_ATTACHED_DIALOG,通过不同的TYPE层级划分我们可以找到置于常规Dialog之上的WindowManager LayoutParams 属性,例如TYPE_SYSTEM_ALERT与TYPE_TOAST,设置了这两个属性的布局是可以将常规Dialog完全遮盖的。他们的区别在于一个是系统级别的Dialog一个是Toast,系统Dialog需要申请权限。所以我们的第一个方案就是可遮挡的Dialog使用常规Dialog,语音提示框采用TYPE_SYSTEM_ALERT。但是都知道安卓有一个无法逃避的问题,就是厂商定制,在MUI的framework层,出于对“安全”的考虑,默认为用户关闭了悬浮窗权限,也就是是说设置了TYPE_SYSTEM_ALERT属性的视图默认是无法显示的,需要用户手动开启权限以后方可显示。
虽然可以在用户启动的时候根据用户机型选择跳转开启权限页,但作为一个有情怀的开发这种不完美的体验还是不能接受的。根据之前对安卓视图层级的学习,我们有了第二套方案。应用视图是存放于mContentParent他与Activity同属TYPE_APPLICATION Window层级属于最下层,常规Dialog的层级是TYPE_APPLICATION_ATTACHED_DIALOG,所以我们将常规Dialog作为最上层不可遮挡的提示框,下面只需考虑可遮挡的弹窗与语音控制两层即可。因为语音控制层需要能够遮挡提示弹窗,所以需要语音控制层在弹窗的上层,经过之前的学习,我们把弹窗加入到mContentParent,把语音控制层添加到DecorView层即可完美的解决问题。mContentParent为一个FrameLayout,应用视图通过sentContentView率先添加到mContentParent中,作为提示弹窗,添加顺序一定相对应用视图置后,所以当提示弹窗再次向mContentParent添加的时候,即会添加到应用视图之上。而DecorView是mContentParent的父容器,也是一个FrameLayout,添加语音提示框的时候mContentParent一定已经存在,所以添加的时候一定会在mContentParent之上。

就这样,一个看似复杂的需求通过对安卓源码的探究完美的解决了,很多时候当我们遇到难以解决的问题,不妨试试回到问题的原点,思考一下问题的本质,很多时候都会有不一样的发现。

阅读全文

与androidview顶层相关的资料

热点内容
卫星锅加密卡那里收购 浏览:56
小米工具文件夹选项在哪里 浏览:53
md5磁盘加密 浏览:640
单片机x地址 浏览:208
回车键失灵运行命令如何使用 浏览:984
电脑一键解压缩的软件 浏览:171
怎么关闭手机通讯录对外app 浏览:370
我的世界如何强行进入一个满人的服务器 浏览:653
什么app可以查询会考成绩 浏览:389
程序员能创造的价值 浏览:259
服务器上的redis是什么意思 浏览:379
软件产品经理与程序员 浏览:922
高中生程序员 浏览:892
ps处理pdf 浏览:723
服务器c1什么意思 浏览:222
哈尔滨手机什么app拍违章有奖励 浏览:479
盗贼用什么app最好 浏览:904
51单片机如何测量电导率 浏览:500
移动花卡怎么使用app流量 浏览:556
个税算法2021表格公式解读 浏览:175