自定义文本编辑器是
EditText
组件或
WebView
个文本 widget,
不过,通过实现
onCreateInputConnection()
回调,在视图获得焦点并且系统请求
InputConnection
视图
对
onCheckIsTextEditor()
应返回 true
。
在自定义文本编辑器中支持触控笔手写
Android 14(API 级别 34)及更高版本支持标准 Android 中的触控笔输入 默认使用文本输入组件(请参阅文本中的触控笔输入 字段)。 不过,自定义文本输入字段(或编辑器)需要进行额外的开发。
如需创建自定义文本编辑器,请执行以下操作:
- 启用手写功能
- 声明手写支持
- 支持手写手势(选择、删除、插入等)
- 向 IME 提供光标位置和其他位置数据
- 显示触控笔手写悬停图标
启用手写功能
如果一个视图仅由一个文本编辑器组成,则视图系统可以 自动为视图启动触控笔手写功能。否则,视图必须 实现自己的手写启动逻辑。
自动开始手写
如果视图只显示一个文本编辑器而没有其他内容,则该视图可以选择
通过调用 View 系统的自动手写启动,
setAutoHandwritingEnabled(true)
。
启用自动手写功能后,触控笔动作会从视图内的任意位置开始 手写边界会自动启动手写模式。输入法 编辑器(IME)接收 触控笔动作事件并提交识别出的文本。
![包含矩形的输入字段,用于指示触控笔动作事件的检测边界。](https://developer.android.google.cn/static/images/develop/ui/compose/touch-input/stylus-input/shared/edittext_handwriting_bounds.png?authuser=9&hl=nb)
EditText
字段内的手写内容。
自定义手写功能
如果视图除了单个文本之外,还包含多个文本编辑器或内容 编辑器,视图必须实现自己的手写启动逻辑,如下所示:
跟踪视图内显示的所有文本编辑器。
-
当触控笔在文本编辑器的手写边界内移动时, 聚焦于文本编辑器(如果尚未聚焦)。
如果编辑器尚未获得焦点,请使用新的 IME 重启编辑器 调用
InputMethodManager#restartInput()
。通过调用以下方法来启动触控笔手写会话:
InputMethodManager#startStylusHandwriting()
。
如果文本编辑器位于可滚动视图内,触控笔在
的手写边界应被视为手写,而不是滚动。使用
ViewParent#requestDisallowInterceptTouchEvent()
防止可滚动祖先视图拦截来自文本的触摸事件
编辑器。
API 详细信息
MotionEvent#getToolType()
- 指示MotionEvent
是否来自触控笔(如果是的话) 返回值是TOOL_TYPE_STYLUS
或TOOL_TYPE_ERASER
。InputMethodManager#isStylusHandwritingAvailable()
- 指示 IME 是否支持触控笔手写。调用 方法,然后再在每次调用InputMethodManager#startStylusHandwriting()
之前调用该方法。 因为手写功能的可用性可能已更改InputMethodManager#startStylusHandwriting()
— 使 IME 进入手写模式。一个ACTION_CANCEL
动作事件会分派给应用,以取消当前手势。触控笔 不再将动作事件分派给应用。已分派给的当前手势的触控笔动作事件 系统会将应用转发到 IME。必须输入 IME 才能显示触控笔墨水 IME 通过该窗口接收所有后续
MotionEvent
对象。 IME 使用InputConnection
API。如果 IME 无法进入手写模式,则此方法调用为空操作。
声明手写支持
在填写
EditorInfo
参数
/
View#onCreateInputConnection(EditorInfo)
次通话
setStylusHandwritingEnabled()
,用于告知 IME 文本编辑器支持手写。
声明支持的手势:
setSupportedHandwritingGestures()
和
setSupportedHandwritingGesturePreviews()
。
支持手写手势
IME 可以支持各种手写手势,例如圈出文字以供选择 或在文字上乱涂即可将其删除。
实现自定义编辑器
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)
访问系统的触控笔手写悬停图标。