安卓 怎么判断哪个edittext获得了焦点

安卓 怎么判断哪个edittext获得了焦点,第1张

boolean viewhasFocus()Returns true if this view has focus iteself, or is the ancestor of the view that has focusif(editexthasFocus()) { //to do}

你试试看给spinner添加事件监听器,当点击editText时让editText获取焦点

spinner倾向于listView,对其中单个的组件更倾向于Button的效果,感觉要在这里面使用editText不实际,要么单击后生成一个editText控件,要么干脆使用dialog实现就好了

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

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

首先让我们通过一张层级图来明确几个重要的概念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这个名字可能会有些陌生,其实他就是我们经常使用的应用根布局,即androidRidcontent。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作为最上层不可遮挡的提示框,下面只需考虑可遮挡的d窗与语音控制两层即可。因为语音控制层需要能够遮挡提示d窗,所以需要语音控制层在d窗的上层,经过之前的学习,我们把d窗加入到mContentParent,把语音控制层添加到DecorView层即可完美的解决问题。mContentParent为一个FrameLayout,应用视图通过sentContentView率先添加到mContentParent中,作为提示d窗,添加顺序一定相对应用视图置后,所以当提示d窗再次向mContentParent添加的时候,即会添加到应用视图之上。而DecorView是mContentParent的父容器,也是一个FrameLayout,添加语音提示框的时候mContentParent一定已经存在,所以添加的时候一定会在mContentParent之上。

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

这是由系统强制产生的效果,在输入法打开的状态下,当前拥有输入焦点的控件一定要出现在当前屏幕的可视范围内(这样产生的效果就是看起来页面好像被输入法的虚拟键盘挤压一样),否则你通过输入法输入的字符都看不到究竟输出到哪里了,大部分人遇到这种情况都会产生一种恐慌的心理,从而造成不良的使用体验。因此这种效果是必须的,没有解决方案。如果你想让文本框在输入数据的时候其他元素也要出现在屏幕上(比如你中的那个圆角按钮),你可以把这些元素做成绝对定位或固定定位的,这样在页面被挤压时候它们也会被顶上来。

不知道你是不是做开发的,这是跟这个输入框的属性有关的。我做android开发的,ios不太清楚。

这类输入框是控件EditText,,只需在EditText加一个属性android:imeOptions="actionSearch",这是输入框获取焦点d出软件盘时,就会有搜索,相应的还有android:imeOptions="actionSend"(发送)   android:imeOptions="actionNext"(下一项),android:imeOptions="actionDone"(完成),android:imeOptions="actionGo"(前往)等等,也就是说用户本身是不能决定的。如图

以上就是关于安卓 怎么判断哪个edittext获得了焦点全部的内容,包括:安卓 怎么判断哪个edittext获得了焦点、安卓开发中的控件spinner,我在它的下面加了一个edittext,为什么edittext不能输入呢,也没有光标闪动。、安卓视图层级大揭秘等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/9346243.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-27
下一篇 2023-04-27

发表评论

登录后才能评论

评论列表(0条)

保存