自定义文本编辑器是
EditText 组件或
WebView 个文本 widget,
不过,通过实现
onCreateInputConnection()
回调,在视图获得焦点并且系统请求
InputConnection
视图
对
onCheckIsTextEditor()
应返回 true。
在自定义文本编辑器中支持触控笔手写
Android 14(API 级别 34)及更高版本支持标准 Android 中的触控笔输入
默认使用文本输入组件(请参阅文本中的触控笔输入
字段)。
不过,自定义文本输入字段(或编辑器)需要进行额外的开发。
如需创建自定义文本编辑器,请执行以下操作:
启用手写功能
声明手写支持
支持手写手势(选择、删除、插入等)
向 IME 提供光标位置和其他位置数据
显示触控笔手写悬停图标
启用手写功能
如果一个视图仅由一个文本编辑器组成,则视图系统可以
自动为视图启动触控笔手写功能。否则,视图必须
实现自己的手写启动逻辑。
自动开始手写
如果视图只显示一个文本编辑器而没有其他内容,则该视图可以选择
通过调用 View 系统的自动手写启动,
setAutoHandwritingEnabled(true)。
启用自动手写功能后,触控笔动作会从视图内的任意位置开始
手写边界会自动启动手写模式。输入法
编辑器(IME)接收
触控笔动作事件并提交识别出的文本。
图 1. EditText 字段内的手写内容。
自定义手写功能
如果视图除了单个文本之外,还包含多个文本编辑器或内容
编辑器,视图必须实现自己的手写启动逻辑,如下所示:
通过调用
setAutoHandwritingEnabled(false)。
跟踪视图内显示的所有文本编辑器。
在
dispatchTouchEvent()。
当触控笔在文本编辑器的手写边界内移动时,
聚焦于文本编辑器(如果尚未聚焦)。
如果编辑器尚未获得焦点,请使用新的 IME 重启编辑器
调用
InputMethodManager#restartInput()。
通过调用以下方法来启动触控笔手写会话:
InputMethodManager#startStylusHandwriting()。
。
注意: 默认情况下,EditText 的手写边界包括 40 dp
垂直内边距和水平内边距为 10 dp(参见图 1)。匹配这些
设置边界。
如果文本编辑器位于可滚动视图内,触控笔在
的手写边界应被视为手写,而不是滚动。使用
ViewParent#requestDisallowInterceptTouchEvent()
防止可滚动祖先视图拦截来自文本的触摸事件
编辑器。
API 详细信息
MotionEvent#getToolType()
- 指示 MotionEvent 是否来自触控笔(如果是的话)
返回值是
TOOL_TYPE_STYLUS
或
TOOL_TYPE_ERASER。
注意: 当用户按触控笔上的橡皮擦按钮,然后做出动作时,
则动作事件返回类型为 TOOL_TYPE_ERASER。开始
手写模式,并让 IME 确定如何识别触控笔
移动。
InputMethodManager#isStylusHandwritingAvailable()
- 指示 IME 是否支持触控笔手写。调用
方法,然后再在每次调用 InputMethodManager#startStylusHandwriting() 之前调用该方法。
因为手写功能的可用性可能已更改
InputMethodManager#startStylusHandwriting()
— 使 IME 进入手写模式。一个
ACTION_CANCEL
动作事件会分派给应用,以取消当前手势。触控笔
不再将动作事件分派给应用。
已分派给的当前手势的触控笔动作事件
系统会将应用转发到 IME。必须输入 IME 才能显示触控笔墨水
IME 通过该窗口接收所有后续 MotionEvent 对象。
IME 使用
InputConnection
API。
如果 IME 无法进入手写模式,则此方法调用为空操作。
注意 :只有在startStylusHandwriting()
view 参数具有焦点,且具有有效的输入连接。窗口
该视图也必须具有焦点。
声明手写支持
在填写
EditorInfo 参数
/
View#onCreateInputConnection(EditorInfo) 次通话
setStylusHandwritingEnabled(),用于告知 IME 文本编辑器支持手写。
声明支持的手势:
setSupportedHandwritingGestures()
和
setSupportedHandwritingGesturePreviews()。
支持手写手势
IME 可以支持各种手写手势,例如圈出文字以供选择
或在文字上乱涂即可将其删除。
您的浏览器不支持视频标记。
图 2. 圈起即可选择文字。
。
您的浏览器不支持视频标记。
。
图 3.在文字上乱涂即可删除文字。
实现自定义编辑器
InputConnection#performHandwritingGesture()
和
InputConnection#previewHandwritingGesture()
来支持不同的
HandwritingGesture
类型,例如
SelectGesture、
DeleteGesture和
InsertGesture。
在填充 EditorInfo 实参时声明支持的手写手势
最多显示 View#onCreateInputConnection(EditorInfo) 个(请参阅声明手写内容)
支持部分)。
API 详细信息
InputConnection#performHandwritingGesture(HandwritingGesture, Executor,
IntConsumer)
— 实现手势。HandwritingGesture 参数包含
位置信息,用于确定要在文字中的什么位置
执行相应手势例如,SelectGesture 提供了一个
RectF 对象,
用于指定选定的文本范围,InsertGesture 用于提供
PointF 对象
用于指定要插入文本的文本偏移量。
使用 Executor 和
IntConsumer 参数
返回操作结果。当执行器和
提供了使用方参数,则使用 Executor 来调用
IntConsumer#accept()、
例如:
executor.execute { consumer.accept(HANDWRITING_GESTURE_RESULT_SUCCESS) }
HandwritingGesture#getFallbackText()
- 提供 IME 在光标位置提交的后备文本(如果没有
相应文字位于手写手势区域下方。
有时,IME 无法确定触控笔手势
用于执行手势操作或手写文本。自定义文本
编辑器负责确定用户的意图并执行
手势位置处的适当操作(具体取决于上下文)。
例如,如果 IME 无法确定用户是不是想要绘制
向下插入符号 ⋁ 执行插入空格手势或手写
字母“v”IME 可以发送包含回退文本“v”的 InsertGesture。
编辑器应首先尝试执行插入空格的手势。如果
手势(例如,该地点没有文字)
),编辑器应回退为插入“v”光标
排名。
InputConnection#previewHandwritingGesture(PreviewableHandwritingGesture,
CancellationSignal)
— 预览正在进行的手势。例如,当用户开始绘制
画圈圈出一些文字,即可实时预览所选文字,
会随着用户继续绘制而持续显示和不断更新。仅特定
手势类型是可预览的(请参阅
PreviewableHandwritingGesture)。
IME 可以使用 CancellationSignal 参数取消
预览。如果其他事件中断预览(例如文本被更改)
以编程方式或发生新的 InputConnection 命令时),自定义编辑器
可以取消预览。
预览手势仅用于显示,不应更改编辑器的
状态。例如,SelectGesture 预览会隐藏编辑器的当前
选择范围,并突出显示手势预览范围。但是,一旦
预览被取消时,编辑器应恢复其之前的选择范围。
提供光标位置和其他位置数据
在手写模式下,IME 可以请求光标位置和其他位置数据
使用
InputConnection#requestCursorUpdates()。
自定义编辑器以调用
InputMethodManager#updateCursorAnchorInfo(View,
CursorAnchorInfo)。
其中的数据
CursorAnchorInfo
与触控笔手写相关的实用信息,
CursorAnchorInfo.Builder
方法:
setInsertionMarkerLocation()
– 设置光标的位置。IME 使用该值添加动画效果
手写内容。
setEditorBoundsInfo()
— 设置编辑器的边界和手写边界。IME 使用
此数据将 IME 的手写工具栏定位在屏幕上。
addVisibleLineBounds()
— 设置所有可见(或部分可见)文本行的边界
编辑器。IME 使用行边界来提高识别准确性
以及手写手势
setTextAppearanceInfo()
— 使用派生自文本的信息设置文本外观
输入字段。IME 使用该信息设置手写墨水样式。
显示触控笔手写悬停图标
当触控笔悬停在
自定义文本编辑器的手写边界,并且所选 IME 支持
触控笔手写
(InputMethodManager#isStylusHandwritingAvailable())。
替换
View#onResolvePointerIcon()
以获取触控笔手写的悬停图标。在替换项中,调用
PointerIcon.getSystemIcon(context, PointerIcon.TYPE_HANDWRITING)
访问系统的触控笔手写悬停图标。
其他资源
文本字段中的触控笔输入