android获取焦点,android webview 焦点

Android EditText获取焦点并弹出软键盘

1、首先,在xml文件中通过让edittext获取焦点

月湖ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为创新互联公司的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:13518219792(备注:SSL证书合作)期待与您的合作!

EditText

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:padding="17dp"

    android:textColor="#333333"

    android:textColorHint="#999999"

    android:hint="请输入课件描述..."

    android:gravity="top|left"

    android:background="@null"

   

    requestFocus/

/EditText

2、在清单文件中给activity添加android:windowSoftInputMode=”stateVisible”属性,这样一进入这个页面的时候光标就自动显示,软键盘也显示出来

activity

        android:name=".wonderfulmoment.AddCourseWareDescriptionActivity"

        android:windowSoftInputMode="stateVisible"/activity

Android 输入法窗口焦点获取流程(2) ,输入法窗口和应用窗口绑定

基于Android9.x

Window和Session创建成功后,窗口的下一步流程为获取焦点

我们看下焦点获取过程,跟输入法相关的流程

两个Activity切换时,对应的状态变化过程为:

以下是Activity窗口初次获取焦点的流程

当两个activity 切换时,失去焦点的窗口调用过程如下:

对应的,获取焦点的额窗口的调用过程如下:

当B窗口的状态切换到RESUMED时,当窗口的focus可能变化时,会调用updateFocusedWindowLocked

在该方法中,判断,如果还没有执行startInputInner方法,则执行startInputInner方法,否则,直接执行startInputOrWindowGainedFocus方法

主要流程:

1:设置controlFlags的flag为CONTROL_WINDOW_FIRST

2:检查是否已经执行过startInputInner,没有的话执行startInputInner--startInputOrWindowGainedFocus;否则,直接执行startInputOrWindowGainedFocus

两条路径,携带的startInputReason参数不一样

主要流程:

1:检查要启动和退出的ServedView是否为同一个,如果为同一个,则表示已经执行过startInputInner,则返回false,表示不再执行startInputInner

2:如果获取焦点的是EditorText,会创建跟IMS通信的mServedInputConnectionWrapper对象

主要流程:

1:创建EditorInfo对象tba,这个参数对TextView布局才有意义,它的初始化是在mServedView的onCreateInputConnection完成实例化的

2:根据EditorInfo创建一个InputConnection对象,输入法应用通过该对象,完成输入内容到输入框的传递;ACTIVITY获取焦点场景,该对象

为null,因为没有要输入的对象

startInputOrWindowGainedFocus携带的参数

startInputReason = 1

表示,该流程是窗口获取焦点过程

mClient

应用层创建的IInputMethodClient对象,为服务层提供应用层的各个回调方法

该方法跟应用进程首次创建时Session时,传递到IMMS的对象是同一个对象

windowGainingFocus:

应用层的ViewRootImpl$W对象

controlFlags |= CONTROL_START_INITIAL;

表示window窗口刚开始获取焦点

softInputMode = SOFT_INPUT_ADJUST_RESIZE , 允许调整输入法窗口,避免被其他窗口遮挡

tba , EditorInfo对象

servedContext

null

missingMethodFlags

ic等于null的情况下,为0

当应用层传递的W对象windowToken不为null的时候,则创建windowGainedFocus对象,返回给app

结果返回后,会对IMM的对象进行赋值

如此,进入一个窗口,获取窗口焦点过程,窗口与输入法相关的流程,就结束了。

下一篇:输入法在输入框弹出流程

Android输入法(3),弹出流程

android tv常见问题(一)焦点查找规律

Recyclerview聚焦到最后一个Item,继续按下键,焦点保持不变。

Recyclerview聚焦到最后一个Item,继续按下键,焦点会跳出RecyclerView,跳到附近的View上。

那么当Recyclerview滑动到最底部时,按下键,Android系统是如何找到下一个需要被聚焦的view的呢?我们把断点打在ViewGroup的focusSearch方法上,可以看到从ViewRootImp的performFocusNavigation方法开始,依次调用了如下方法。

View并不会直接去找焦点,而是交给它的parent去找。

焦点会逐级的交给父ViewGroup的focusSearch方法去处理,直到最外层的布局,最后实际上是调用了FocusFinder的findNextFocus方法去寻找新的焦点。

但是这里要注意的是,RecyclerView和其他的ViewGroup不一样,它自己重写了focusSearch方法。所以在焦点查找委托到达到DecorView之前,会先执行RecyclerView的focusSearch方法。

那么,RecyclerView和其他ViewGroup在寻找焦点方面有什么不一样呢? 为什么RecyclerView要重写ViewGroup的焦点查找机制呢 ?想知道这些问题的答案,那我们首先要知道ViewGroup的焦点查找机制。

ViewGroup的焦点查找机制的核心其实就是FocusFinder的findNextFocus方法。

主要步骤:

主要注意三点:

在addFocusables之后,找到指定方向上与当前focused距离最近的view。在进行查找之前,会统一坐标系。

总的来说就是根据当前focused的位置以及按键的方向,循环比较focusable集合中哪一个最适合,然后返回最合适的view,焦点查找就算完成了。

用于比较的方法。分别是将 当前聚焦的view , 当前遍历到的focusable 和 目前为止最合适的focusable (i = 0时是优先级最低的rect)进行比较。

判断是否可以做为候选。可以看作是一个初步筛选的方法,但是到底哪个更好还需要看beamBeat方法,这个方法会将通过筛选的focusable和当前最合适的focusable进行比较,选出更合适的一个。

到这里为止ViewGroup的focusSearch方法基本上就讲完了。那么下面来看一下RecyclerView的focusSearch方法是如何实现焦点查找的。

前面讲到了,该方法主要是为了解决 RecyclerView聚焦在按键方向上、当前屏幕区域内可见的最后一个item时,当前不可见的下一个item将无法获得焦点。

这个方法是由LayoutManager来实现的,这就是RecyclerView的针对上面提到的情况的焦点查找方法。这里主要分析LinearLayoutManager中实现的该方法,如果在使用其他的LayoutManager时出现RecyclelerView焦点不符合预期的话,可以查看对于LayoutManager下的onFocusSearchFailed方法。

主要关注findPartiallyOrCompletelyInvisibleChildClosestToEnd方法,通过这个方法的命名我们大致就可以看出来这个方法的作用了。这个方法主要会 根据当前RecyclerVIew的正逆序以及按键方向,找出最近一个部分或完全不可见的View 。

这个方法是RecyclerView内部的方法,和FocusFinder中的isCandidate方法的逻辑可以说几乎是一摸一样的。

到此为止ViewGroup的focusSearch和RecyclerVIew的focusSearch都分析完了。我们已经知道RecyclerView滑动到最底部的时候,发生了哪些焦点行为,那么解决起来就比较简单了。

结合KeyEvent事件的流转,处理焦点的时机,按照优先级(顺序)依次是:

以上任一处都可以指定焦点,一旦消费了就不再往下走。

比如前面说到了RecyclerView就是通过重写focusSearch方法对边界上部分可见或不可见的view的焦点查找进行了特殊处理。

重写RecyclerView的focusSearch方法

Android TV 焦点原理源码解析

相信很多刚接触AndroidTV开发的开发者,都会被各种焦点问题给折磨的不行。不管是学技术还是学习其他知识,都要学习和理解其中原理,碰到问题我们才能得心应手。下面就来探一探Android的焦点分发的过程。

Android焦点事件的分发是从ViewRootImpl的processKeyEvent开始的,源码如下:

源码比较长,下面我就慢慢来讲解一下具体的每一个细节。

dispatchKeyEvent方法返回true代表焦点事件被消费了。

ViewGroup的dispatchKeyEvent()方法的源码如下:

(2)ViewGroup的dispatchKeyEvent执行流程

(3)下面再来瞧瞧view的dispatchKeyEvent方法的具体的执行过程

惊奇的发现执行了onKeyListener中的onKey方法,如果onKey方法返回true,那么dispatchKeyEvent方法也会返回true

可以得出结论:如果想要修改ViewGroup焦点事件的分发,可以这么干:

注意:实际开发中,理论上所有焦点问题都可以通过给dispatchKeyEvent方法增加监听来来拦截来控制。

(1)dispatchKeyEvent方法返回false后,先得到按键的方向direction值,这个值是一个int类型参数。这个direction值是后面来进行焦点查找的。

(2)接着会调用DecorView的findFocus()方法一层一层往下查找已经获取焦点的子View。

ViewGroup的findFocus方法如下:

View的findFocus方法

说明:判断view是否获取焦点的isFocused()方法, (mPrivateFlags PFLAG_FOCUSED) != 0 和view 的isFocused()方法是一致的。

其中isFocused()方法的作用是判断view是否已经获取焦点,如果viewGroup已经获取到了焦点,那么返回本身即可,否则通过mFocused的findFocus()方法来找焦点。mFocused其实就是ViewGroup中获取焦点的子view,如果mView不是ViewGourp的话,findFocus其实就是判断本身是否已经获取焦点,如果已经获取焦点了,返回本身。

(3)回到processKeyEvent方法中,如果findFocus方法返回的mFocused不为空,说明找到了当前获取焦点的view(mFocused),接着focusSearch会把direction(遥控器按键按下的方向)作为参数,找到特定方向下一个将要获取焦点的view,最后如果该view不为空,那么就让该view获取焦点。

(4)focusSearch方法的具体实现。

focusSearch方法的源码如下:

可以看出focusSearch其实是一层一层地网上调用父View的focusSearch方法,直到当前view是根布局(isRootNamespace()方法),通过注释可以知道focusSearch最终会调用DecorView的focusSearch方法。而DecorView的focusSearch方法找到的焦点view是通过FocusFinder来找到的。

(5)FocusFinder是什么?

它其实是一个实现 根据给定的按键方向,通过当前的获取焦点的View,查找下一个获取焦点的view这样算法的类。焦点没有被拦截的情况下,Android框架焦点的查找最终都是通过FocusFinder类来实现的。

(6)FocusFinder是如何通过findNextFocus方法寻找焦点的。

下面就来看看FocusFinder类是如何通过findNextFocus来找焦点的。一层一层往下看,后面会执行findNextUserSpecifiedFocus()方法,这个方法会执行focused(即当前获取焦点的View)的findUserSetNextFocus方法,如果该方法返回的View不为空,且isFocusable = true isInTouchMode() = true的话,FocusFinder找到的焦点就是findNextUserSpecifiedFocus()返回的View。

(7)findNextFocus会优先根据XML里设置的下一个将获取焦点的View ID值来寻找将要获取焦点的View。

看看View的findUserSetNextFocus方法内部都干了些什么,OMG不就是通过我们xml布局里设置的nextFocusLeft,nextFocusRight的viewId来找焦点吗,如果按下Left键,那么便会通过nextFocusLeft值里的View Id值去找下一个获取焦点的View。

可以得出以下结论:

1. 如果一个View在XML布局中设置了focusable = true isInTouchMode = true,那么这个View会优先获取焦点。

2. 通过设置nextFocusLeft,nextFocusRight,nextFocusUp,nextFocusDown值可以控制View的下一个焦点。

Android焦点的原理实现就这些。总结一下:

为了方便同志们学习,我这做了张导图,方便大家理解~


网页标题:android获取焦点,android webview 焦点
标题网址:http://myzitong.com/article/dscjdcp.html