Files
Android-pyApi/android_pyapi/android/text_method.py
T
shuiyu1123 a51854455b feat: 大规模扩充至212个模块/175K行代码 — 覆盖android/java/javax/org/dalvik全包
- android/ 167个模块 (app/content/os/view/widget/graphics/media/hardware/net/telephony/provider等)
- java/ 35个模块 (lang/io/util/net/nio/security/crypto/sql/beans/rmi/awt等)
- javax/ 4个模块 (net/crypto/security/sql)
- org/ 5个模块 (json/w3c_dom/xml_sax/xml_pull/apache_http)
- dalvik/ 1个模块 (system)
- ~3053个类/接口,方法签名完全对齐Android SDK
- 桌面跨平台运行 (Windows/macOS/Linux)
- 修复所有导入错误和Python关键字冲突
2026-06-24 14:15:56 +00:00

676 lines
25 KiB
Python

"""
Android text.method 包 — KeyListener, MovementMethod, TransformationMethod 等
方法签名完全对齐 Android SDK
"""
from __future__ import annotations
import sys
import time
from typing import Any, Dict, List, Optional, Set, Tuple
from .._core import Stub, AndroidOnlyError
from ..java.lang import RuntimeException
IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {})
__all__ = [
"KeyListener",
"MetaKeyKeyListener",
"NumberKeyListener",
"DigitsKeyListener",
"TextKeyListener",
"MovementMethod",
"ArrowKeyMovementMethod",
"LinkMovementMethod",
"Touch",
"BaseMovementMethod",
"ScrollingMovementMethod",
"WordIterator",
"PasswordTransformationMethod",
"TransformationMethod",
"TransformationMethod2",
"SingleLineTransformationMethod",
"HideReturnsTransformationMethod",
"TimeDisplayTruncationMethod",
"DateTimeKeyListener",
"DateKeyListener",
"TimeKeyListener",
]
# ═══════════════════════════════════════════════════════════════
# KeyListener
# ═══════════════════════════════════════════════════════════════
class KeyListener(Stub):
"""KeyListener — 按键监听器接口 (桌面存根)"""
META_SHIFT_MASK = 0x1
META_ALT_MASK = 0x2
META_SYM_MASK = 0x4
META_CTRL_MASK = 0x1000
META_META_MASK = 0x10000
META_CAPS_LOCK = 0x100000
META_ALT_LOCK = 0x200000
META_SYM_LOCK = 0x400000
META_SELECTING = 0x800000
META_SHIFTING = 0x1000000
def __init__(self):
super().__init__()
self._input_type = 0
self._meta_state = 0
def clearMetaKeyState(self, view: Any, content: Any, states: int) -> None:
"""清除元键状态"""
self._meta_state = self._meta_state & ~states
def getInputType(self) -> int:
"""获取输入类型"""
return self._input_type
def onKeyDown(self, view: Any, content: Any, keyCode: int, event: Any) -> bool:
"""按键按下事件"""
return False
def onKeyUp(self, view: Any, content: Any, keyCode: int, event: Any) -> bool:
"""按键释放事件"""
return False
def onKeyOther(self, view: Any, content: Any, event: Any) -> bool:
"""其他按键事件"""
return False
@staticmethod
def metaStateHasNoModifiers(metaState: int) -> bool:
"""检查元状态是否没有修饰键"""
return (metaState & 0x0000FFFF) == 0
@staticmethod
def metaStateHasModifiers(metaState: int, modifiers: int) -> bool:
"""检查元状态是否有指定修饰键"""
return (metaState & modifiers) != 0
@staticmethod
def metaStateFilterDirectionLocked(metaState: int) -> int:
"""过滤方向锁定"""
return metaState & ~(KeyListener.META_CAPS_LOCK | KeyListener.META_ALT_LOCK | KeyListener.META_SYM_LOCK)
def __repr__(self) -> str:
return f"KeyListener(inputType={self._input_type})"
# ═══════════════════════════════════════════════════════════════
# MetaKeyKeyListener
# ═══════════════════════════════════════════════════════════════
class MetaKeyKeyListener(KeyListener):
"""MetaKeyKeyListener — 元键按键监听器 (桌面存根)"""
def __init__(self):
super().__init__()
self._locked_meta: Dict[int, int] = {}
def clearMetaKeyState(self, view: Any, content: Any, states: int) -> None:
"""清除元键状态"""
self._meta_state = self._meta_state & ~states
for state_bit in [KeyListener.META_CAPS_LOCK, KeyListener.META_ALT_LOCK, KeyListener.META_SYM_LOCK]:
if states & state_bit:
self._locked_meta.pop(state_bit, None)
@staticmethod
def resetMetaState(content: Any) -> None:
"""重置元状态"""
if hasattr(content, '_meta_state'):
content._meta_state = 0
def onKeyDown(self, view: Any, content: Any, keyCode: int, event: Any) -> bool:
"""按键按下事件处理"""
return super().onKeyDown(view, content, keyCode, event)
def onKeyUp(self, view: Any, content: Any, keyCode: int, event: Any) -> bool:
"""按键释放事件处理"""
return super().onKeyUp(view, content, keyCode, event)
@staticmethod
def adjustMetaAfterKeypress(content: Any) -> None:
"""按键后调整元状态"""
pass
def handleKeyDown(self, view: Any, content: Any, keyCode: int, event: Any) -> bool:
"""处理按键按下 (内部)"""
return self.onKeyDown(view, content, keyCode, event)
def handleKeyUp(self, view: Any, content: Any, keyCode: int, event: Any) -> bool:
"""处理按键释放 (内部)"""
return self.onKeyUp(view, content, keyCode, event)
@staticmethod
def getMetaState(content: Any) -> int:
"""获取元状态"""
return getattr(content, '_meta_state', 0)
@staticmethod
def getMetaState_ex(content: Any, meta: int) -> bool:
"""检查特定元状态"""
state = getattr(content, '_meta_state', 0)
return (state & meta) != 0
@staticmethod
def isMetaTracker(content: Any) -> bool:
"""检查是否是元追踪器"""
return hasattr(content, '_meta_state')
@staticmethod
def isSelectingMetaTracker(content: Any) -> bool:
"""检查是否是选择元追踪器"""
return hasattr(content, '_meta_state') and (getattr(content, '_meta_state', 0) & KeyListener.META_SELECTING) != 0
@staticmethod
def peekMetaState(content: Any) -> int:
"""窥视元状态"""
return getattr(content, '_meta_state', 0)
def resetLockedMeta(self, content: Any) -> None:
"""重置锁定元键"""
self._locked_meta.clear()
def clearLockedMeta(self, content: Any) -> None:
"""清除锁定元键"""
self._locked_meta.clear()
@staticmethod
def releaseAllMetaKeys(content: Any) -> None:
"""释放所有元键"""
if hasattr(content, '_meta_state'):
content._meta_state = 0
def toString(self) -> str:
return f"MetaKeyKeyListener(metaState={self._meta_state}, locked={self._locked_meta})"
# ═══════════════════════════════════════════════════════════════
# NumberKeyListener
# ═══════════════════════════════════════════════════════════════
class NumberKeyListener(MetaKeyKeyListener):
"""NumberKeyListener — 数字按键监听器 (桌面存根)"""
_ACCEPTED_CHARS: str = ""
def __init__(self):
super().__init__()
self._input_type = 0x0002 # TYPE_CLASS_NUMBER
def getAcceptedChars(self) -> List[str]:
"""获取接受的字符列表"""
return list(self._ACCEPTED_CHARS)
def filter(self, source: str, start: int, end: int, dest: str, dstart: int, dend: int) -> str:
"""过滤输入,只保留接受的字符"""
result = ""
for i in range(start, end):
ch = source[i] if i < len(source) else ''
if ch in self._ACCEPTED_CHARS:
result += ch
return result if result != source[start:end] else ""
def lookup(self, key: int, event: Any) -> Optional[str]:
"""查找按键映射的字符"""
key_map = {
7: '0', 8: '1', 9: '2', 10: '3', 11: '4',
12: '5', 13: '6', 14: '7', 15: '8', 16: '9',
}
return key_map.get(key)
def onKeyDown(self, view: Any, content: Any, keyCode: int, event: Any) -> bool:
"""按键按下事件"""
char = self.lookup(keyCode, event)
if char and char in self._ACCEPTED_CHARS:
return True
return False
# ═══════════════════════════════════════════════════════════════
# DigitsKeyListener
# ═══════════════════════════════════════════════════════════════
class DigitsKeyListener(NumberKeyListener):
"""DigitsKeyListener — 数字按键监听器 (桌面存根)"""
_instances: Dict[str, "DigitsKeyListener"] = {}
def __init__(self, accepted: str = "0123456789"):
super().__init__()
self._ACCEPTED_CHARS = accepted
self._input_type = 0x0002
@staticmethod
def getInstance(locale: Any = None, sign: bool = False, decimal: bool = False) -> "DigitsKeyListener":
"""获取实例"""
key = f"{locale}_{sign}_{decimal}"
if key not in DigitsKeyListener._instances:
accepted = "0123456789"
if sign:
accepted += "-"
if decimal:
accepted += "."
DigitsKeyListener._instances[key] = DigitsKeyListener(accepted)
return DigitsKeyListener._instances[key]
def getAcceptedChars(self) -> List[str]:
return list(self._ACCEPTED_CHARS)
def filter(self, source: str, start: int, end: int, dest: str, dstart: int, dend: int) -> str:
return super().filter(source, start, end, dest, dstart, dend)
# ═══════════════════════════════════════════════════════════════
# TextKeyListener
# ═══════════════════════════════════════════════════════════════
class TextKeyListener(MetaKeyKeyListener):
"""TextKeyListener — 文本按键监听器 (桌面存根)"""
CAP_MODE_CHARACTERS = 0x1
CAP_MODE_WORDS = 0x2
CAP_MODE_SENTENCES = 0x4
_instance: Optional["TextKeyListener"] = None
def __init__(self):
super().__init__()
self._input_type = 0x0001 # TYPE_CLASS_TEXT
self._auto_cap_mode = 0
@staticmethod
def getInstance() -> "TextKeyListener":
"""获取单例实例"""
if TextKeyListener._instance is None:
TextKeyListener._instance = TextKeyListener()
return TextKeyListener._instance
def clear(self, view: Any, content: Any) -> None:
"""清除内容"""
if hasattr(content, 'clear'):
content.clear()
def release(self, view: Any) -> None:
"""释放资源"""
pass
def onKeyDown(self, view: Any, content: Any, keyCode: int, event: Any) -> bool:
return True
def onKeyUp(self, view: Any, content: Any, keyCode: int, event: Any) -> bool:
return True
def toString(self) -> str:
return f"TextKeyListener(capMode={self._auto_cap_mode})"
# ═══════════════════════════════════════════════════════════════
# MovementMethod
# ═══════════════════════════════════════════════════════════════
class MovementMethod(Stub):
"""MovementMethod — 移动方法接口 (桌面存根)"""
def __init__(self):
super().__init__()
self._movement_meta_state = 0
def initialize(self, view: Any, content: Any) -> None:
"""初始化"""
pass
def onKeyDown(self, view: Any, content: Any, keyCode: int, event: Any) -> bool:
"""按键按下"""
return False
def onKeyUp(self, view: Any, content: Any, keyCode: int, event: Any) -> bool:
"""按键释放"""
return False
def onTakeFocus(self, view: Any, content: Any, direction: int) -> bool:
"""获取焦点"""
return False
def canSelectArbitrarily(self) -> bool:
"""能否任意选择"""
return False
def dispatchTouchEvent(self, view: Any, content: Any, event: Any) -> bool:
"""分发触摸事件"""
return False
def onGenericMotionEvent(self, view: Any, content: Any, event: Any) -> bool:
"""通用运动事件"""
return False
def getMovementMetaState(self) -> int:
"""获取移动元状态"""
return self._movement_meta_state
def setMovementMetaState(self, state: int) -> None:
"""设置移动元状态"""
self._movement_meta_state = state
def toString(self) -> str:
return f"{self.__class__.__name__}@MovementMethod"
# ═══════════════════════════════════════════════════════════════
# ArrowKeyMovementMethod
# ═══════════════════════════════════════════════════════════════
class ArrowKeyMovementMethod(MovementMethod):
"""ArrowKeyMovementMethod — 箭头键移动方法 (桌面存根)"""
_instance: Optional["ArrowKeyMovementMethod"] = None
def __init__(self):
super().__init__()
@staticmethod
def getInstance() -> "ArrowKeyMovementMethod":
if ArrowKeyMovementMethod._instance is None:
ArrowKeyMovementMethod._instance = ArrowKeyMovementMethod()
return ArrowKeyMovementMethod._instance
def onKeyDown(self, view: Any, content: Any, keyCode: int, event: Any) -> bool:
return True
def canSelectArbitrarily(self) -> bool:
return True
# ═══════════════════════════════════════════════════════════════
# LinkMovementMethod
# ═══════════════════════════════════════════════════════════════
class LinkMovementMethod(MovementMethod):
"""LinkMovementMethod — 链接移动方法 (桌面存根)"""
_instance: Optional["LinkMovementMethod"] = None
def __init__(self):
super().__init__()
@staticmethod
def getInstance() -> "LinkMovementMethod":
if LinkMovementMethod._instance is None:
LinkMovementMethod._instance = LinkMovementMethod()
return LinkMovementMethod._instance
def onKeyDown(self, view: Any, content: Any, keyCode: int, event: Any) -> bool:
return True
def canSelectArbitrarily(self) -> bool:
return False
# ═══════════════════════════════════════════════════════════════
# Touch
# ═══════════════════════════════════════════════════════════════
class Touch(Stub):
"""Touch — 触摸工具类 (桌面存根)"""
def __init__(self):
super().__init__()
self._initial_scroll_x = 0
self._initial_scroll_y = 0
@staticmethod
def getInitialScrollX(widget: Any, content: Any) -> int:
"""获取初始滚动 X"""
return getattr(widget, '_initial_scroll_x', 0)
@staticmethod
def getInitialScrollY(widget: Any, content: Any) -> int:
"""获取初始滚动 Y"""
return getattr(widget, '_initial_scroll_y', 0)
@staticmethod
def scrollTo(widget: Any, content: Any, x: int, y: int) -> None:
"""滚动到指定位置"""
if hasattr(widget, '_scroll_x'):
widget._scroll_x = x
if hasattr(widget, '_scroll_y'):
widget._scroll_y = y
# ═══════════════════════════════════════════════════════════════
# BaseMovementMethod
# ═══════════════════════════════════════════════════════════════
class BaseMovementMethod(MovementMethod):
"""BaseMovementMethod — 基本移动方法 (桌面存根)"""
def __init__(self):
super().__init__()
def onKeyDown(self, view: Any, content: Any, keyCode: int, event: Any) -> bool:
return False
def canSelectArbitrarily(self) -> bool:
return False
# ═══════════════════════════════════════════════════════════════
# ScrollingMovementMethod
# ═══════════════════════════════════════════════════════════════
class ScrollingMovementMethod(BaseMovementMethod):
"""ScrollingMovementMethod — 滚动移动方法 (桌面存根)"""
_instance: Optional["ScrollingMovementMethod"] = None
def __init__(self):
super().__init__()
@staticmethod
def getInstance() -> "ScrollingMovementMethod":
if ScrollingMovementMethod._instance is None:
ScrollingMovementMethod._instance = ScrollingMovementMethod()
return ScrollingMovementMethod._instance
def onKeyDown(self, view: Any, content: Any, keyCode: int, event: Any) -> bool:
return True
# ═══════════════════════════════════════════════════════════════
# WordIterator
# ═══════════════════════════════════════════════════════════════
class WordIterator(Stub):
"""WordIterator — 单词迭代器 (桌面存根)"""
def __init__(self, locale: Optional[Any] = None):
super().__init__()
self._locale = locale
self._text = ""
self._cursor = 0
def setText(self, text: str, start: int, end: int) -> None:
"""设置文本"""
self._text = text[start:end] if end <= len(text) else text[start:]
self._cursor = 0
def next(self) -> int:
"""下一个单词边界"""
self._cursor += 1
return self._cursor
def prev(self) -> int:
"""上一个单词边界"""
self._cursor -= 1
return max(self._cursor, 0)
def getEnd(self) -> int:
"""获取结束位置"""
return len(self._text)
def getBegin(self) -> int:
"""获取开始位置"""
return 0
def isBoundary(self, offset: int) -> bool:
"""检查是否是单词边界"""
return True
# ═══════════════════════════════════════════════════════════════
# TransformationMethod / PasswordTransformationMethod
# ═══════════════════════════════════════════════════════════════
class TransformationMethod(Stub):
"""TransformationMethod — 变换方法接口 (桌面存根)"""
def __init__(self):
super().__init__()
def getTransformation(self, source: Any, view: Any) -> Any:
"""获取变换后的文本"""
return source
def onFocusChanged(self, view: Any, source: Any, focused: bool, direction: int, previouslyFocused: Any) -> None:
"""焦点变化事件"""
pass
class TransformationMethod2(TransformationMethod):
"""TransformationMethod2 — 带长度变化通知的变换方法"""
def __init__(self):
super().__init__()
self._length_changes_allowed = True
def setLengthChangesAllowed(self, allowLengthChanges: bool) -> None:
"""设置是否允许长度变化"""
self._length_changes_allowed = allowLengthChanges
class PasswordTransformationMethod(TransformationMethod):
"""PasswordTransformationMethod — 密码变换方法 (桌面存根)"""
_instance: Optional["PasswordTransformationMethod"] = None
def __init__(self):
super().__init__()
@staticmethod
def getInstance() -> "PasswordTransformationMethod":
if PasswordTransformationMethod._instance is None:
PasswordTransformationMethod._instance = PasswordTransformationMethod()
return PasswordTransformationMethod._instance
def getTransformation(self, source: Any, view: Any) -> Any:
"""将文本转换为掩码字符"""
text = str(source) if source else ""
return "\u2022" * len(text) # bullet character
def onFocusChanged(self, view: Any, source: Any, focused: bool, direction: int, previouslyFocused: Any) -> None:
pass
class SingleLineTransformationMethod(TransformationMethod):
"""SingleLineTransformationMethod — 单行变换方法 (桌面存根)"""
_instance: Optional["SingleLineTransformationMethod"] = None
def __init__(self):
super().__init__()
@staticmethod
def getInstance() -> "SingleLineTransformationMethod":
if SingleLineTransformationMethod._instance is None:
SingleLineTransformationMethod._instance = SingleLineTransformationMethod()
return SingleLineTransformationMethod._instance
def getTransformation(self, source: Any, view: Any) -> Any:
"""移除换行符"""
text = str(source) if source else ""
return text.replace("\n", " ").replace("\r", "")
class HideReturnsTransformationMethod(SingleLineTransformationMethod):
"""HideReturnsTransformationMethod — 隐藏回车变换方法 (桌面存根)"""
_instance: Optional["HideReturnsTransformationMethod"] = None
def __init__(self):
super().__init__()
@staticmethod
def getInstance() -> "HideReturnsTransformationMethod":
if HideReturnsTransformationMethod._instance is None:
HideReturnsTransformationMethod._instance = HideReturnsTransformationMethod()
return HideReturnsTransformationMethod._instance
def getTransformation(self, source: Any, view: Any) -> Any:
text = str(source) if source else ""
return text.replace("\r", "")
class TimeDisplayTruncationMethod(TransformationMethod):
"""TimeDisplayTruncationMethod — 时间显示截断方法 (桌面存根)"""
def __init__(self, max_digits: int = 4):
super().__init__()
self._max_digits = max_digits
def getTransformation(self, source: Any, view: Any) -> Any:
text = str(source) if source else ""
if len(text) > self._max_digits:
return text[:self._max_digits]
return text
# ═══════════════════════════════════════════════════════════════
# DateTimeKeyListener / DateKeyListener / TimeKeyListener
# ═══════════════════════════════════════════════════════════════
class DateTimeKeyListener(NumberKeyListener):
"""DateTimeKeyListener — 日期时间按键监听器 (桌面存根)"""
def __init__(self, locale: Optional[Any] = None):
super().__init__()
self._locale = locale
self._ACCEPTED_CHARS = "0123456789/: "
class DateKeyListener(NumberKeyListener):
"""DateKeyListener — 日期按键监听器 (桌面存根)"""
_instance: Optional["DateKeyListener"] = None
def __init__(self, locale: Optional[Any] = None):
super().__init__()
self._locale = locale
self._ACCEPTED_CHARS = "0123456789/"
@staticmethod
def getInstance(locale: Any = None) -> "DateKeyListener":
if DateKeyListener._instance is None:
DateKeyListener._instance = DateKeyListener(locale)
return DateKeyListener._instance
class TimeKeyListener(NumberKeyListener):
"""TimeKeyListener — 时间按键监听器 (桌面存根)"""
_instance: Optional["TimeKeyListener"] = None
def __init__(self, locale: Optional[Any] = None):
super().__init__()
self._locale = locale
self._ACCEPTED_CHARS = "0123456789:"
@staticmethod
def getInstance(locale: Any = None) -> "TimeKeyListener":
if TimeKeyListener._instance is None:
TimeKeyListener._instance = TimeKeyListener(locale)
return TimeKeyListener._instance