Files
Android-pyApi/android_pyapi/android/view_ext.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

2497 lines
74 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Android View 扩展组件 — ViewOutlineProvider, ViewPropertyAnimator, ViewStructure 等
方法签名完全对齐 Android SDK
"""
from __future__ import annotations
import math
import time
import weakref
import threading
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
from .._core import Stub, AndroidOnlyError
from ..java.lang import RuntimeException
# ═══════════════════════════════════════════════════════════════
# ViewOutlineProvider
# ═══════════════════════════════════════════════════════════════
class ViewOutlineProvider(Stub):
"""ViewOutlineProvider — 视图轮廓提供者"""
BACKGROUND = None
BOUNDS = None
PADDED_BOUNDS = None
def __init__(self):
super().__init__()
def getOutline(self, view: Any, outline: Any) -> None:
"""获取视图轮廓"""
pass
ViewOutlineProvider.BACKGROUND = ViewOutlineProvider()
ViewOutlineProvider.BOUNDS = ViewOutlineProvider()
ViewOutlineProvider.PADDED_BOUNDS = ViewOutlineProvider()
class Outline(Stub):
"""Outline — 轮廓描述"""
MODE_CONVEX_PATH = 2
MODE_EMPTY = 0
MODE_ROUND_RECT = 1
def __init__(self):
super().__init__()
self._alpha: float = 1.0
self._mode: int = self.MODE_EMPTY
self._rect: Tuple[float, float, float, float] = (0, 0, 0, 0)
self._radius: float = 0.0
def setAlpha(self, alpha: float) -> None:
self._alpha = max(0.0, min(1.0, alpha))
def getAlpha(self) -> float:
return self._alpha
def setEmpty(self) -> None:
self._mode = self.MODE_EMPTY
def isEmpty(self) -> bool:
return self._mode == self.MODE_EMPTY
def setRoundRect(self, left: float, top: float, right: float, bottom: float,
radius: float) -> None:
self._mode = self.MODE_ROUND_RECT
self._rect = (left, top, right, bottom)
self._radius = radius
def setOval(self, left: float, top: float, right: float, bottom: float) -> None:
self._mode = self.MODE_ROUND_RECT
self._rect = (left, top, right, bottom)
self._radius = min(right - left, bottom - top) / 2.0
def setConvexPath(self, path: Any) -> None:
self._mode = self.MODE_CONVEX_PATH
def getRect(self) -> Optional[Tuple[float, float, float, float]]:
if self._mode == self.MODE_EMPTY:
return None
return self._rect
def getRadius(self) -> float:
return self._radius
def canClip(self) -> bool:
return self._mode in (self.MODE_ROUND_RECT, self.MODE_CONVEX_PATH)
def toString(self) -> str:
return (f"Outline(mode={self._mode}, alpha={self._alpha}, "
f"radius={self._radius})")
# ═══════════════════════════════════════════════════════════════
# ViewPropertyAnimator
# ═══════════════════════════════════════════════════════════════
class ViewPropertyAnimator(Stub):
"""ViewPropertyAnimator — 视图属性动画器"""
def __init__(self, view: Any = None):
super().__init__()
self._view = weakref.ref(view) if view is not None else None
self._duration: int = 300
self._start_delay: int = 0
self._interpolator: Optional[Any] = None
self._listener: Optional[Callable] = None
self._translation_x: Optional[float] = None
self._translation_y: Optional[float] = None
self._translation_z: Optional[float] = None
self._scale_x: Optional[float] = None
self._scale_y: Optional[float] = None
self._rotation: Optional[float] = None
self._rotation_x: Optional[float] = None
self._rotation_y: Optional[float] = None
self._alpha: Optional[float] = None
self._x: Optional[float] = None
self._y: Optional[float] = None
self._width: Optional[int] = None
self._height: Optional[int] = None
self._running = False
def translationX(self, value: float) -> "ViewPropertyAnimator":
self._translation_x = value
return self
def translationY(self, value: float) -> "ViewPropertyAnimator":
self._translation_y = value
return self
def translationZ(self, value: float) -> "ViewPropertyAnimator":
self._translation_z = value
return self
def rotation(self, value: float) -> "ViewPropertyAnimator":
self._rotation = value
return self
def rotationX(self, value: float) -> "ViewPropertyAnimator":
self._rotation_x = value
return self
def rotationY(self, value: float) -> "ViewPropertyAnimator":
self._rotation_y = value
return self
def scaleX(self, value: float) -> "ViewPropertyAnimator":
self._scale_x = value
return self
def scaleY(self, value: float) -> "ViewPropertyAnimator":
self._scale_y = value
return self
def alpha(self, value: float) -> "ViewPropertyAnimator":
self._alpha = max(0.0, min(1.0, value))
return self
def x(self, value: float) -> "ViewPropertyAnimator":
self._x = value
return self
def y(self, value: float) -> "ViewPropertyAnimator":
self._y = value
return self
def width(self, value: int) -> "ViewPropertyAnimator":
self._width = value
return self
def height(self, value: int) -> "ViewPropertyAnimator":
self._height = value
return self
def setDuration(self, duration: int) -> "ViewPropertyAnimator":
self._duration = max(0, duration)
return self
def getDuration(self) -> int:
return self._duration
def setStartDelay(self, delay: int) -> "ViewPropertyAnimator":
self._start_delay = max(0, delay)
return self
def getStartDelay(self) -> int:
return self._start_delay
def setInterpolator(self, interpolator: Any) -> "ViewPropertyAnimator":
self._interpolator = interpolator
return self
def setListener(self, listener: Optional[Callable]) -> "ViewPropertyAnimator":
self._listener = listener
return self
def withEndAction(self, action: Callable) -> "ViewPropertyAnimator":
self._end_action = action
return self
def withStartAction(self, action: Callable) -> "ViewPropertyAnimator":
self._start_action = action
return self
def start(self) -> None:
if self._running:
return
self._running = True
if self._start_action:
self._start_action()
if self._listener:
self._listener.onAnimationStart(self)
if self._alpha is not None and self._view:
v = self._view()
if v:
v.setAlpha(self._alpha)
if self._listener:
self._listener.onAnimationEnd(self)
if self._end_action:
self._end_action()
def cancel(self) -> None:
self._running = False
if self._listener:
self._listener.onAnimationCancel(self)
def isRunning(self) -> bool:
return self._running
def toString(self) -> str:
return (f"ViewPropertyAnimator(duration={self._duration}, "
f"running={self._running})")
# ═══════════════════════════════════════════════════════════════
# ViewStructure
# ═══════════════════════════════════════════════════════════════
class ViewStructure(Stub):
"""ViewStructure — 视图结构(用于 Assist/autofill)"""
def __init__(self):
super().__init__()
self._text: Optional[str] = None
self._hint: Optional[str] = None
self._className: Optional[str] = None
self._contentDescription: Optional[str] = None
self._id: Optional[int] = None
self._id_package: Optional[str] = None
self._id_type: Optional[str] = None
self._id_entry: Optional[str] = None
self._web_domain: Optional[str] = None
self._input_type: int = 0
self._alpha: float = 1.0
self._elevation: float = 0.0
self._width: int = 0
self._height: int = 0
self._left: int = 0
self._top: int = 0
self._scroll_x: int = 0
self._scroll_y: int = 0
self._children: List[ViewStructure] = []
self._html_info: Optional[Any] = None
self._data_set: Optional[Any] = None
def setText(self, text: str) -> None:
self._text = text
def getText(self) -> Optional[str]:
return self._text
def setHint(self, hint: str) -> None:
self._hint = hint
def getHint(self) -> Optional[str]:
return self._hint
def setClassName(self, class_name: str) -> None:
self._className = class_name
def getClassName(self) -> Optional[str]:
return self._className
def setContentDescription(self, desc: str) -> None:
self._contentDescription = desc
def getContentDescription(self) -> Optional[str]:
return self._contentDescription
def setId(self, id_val: int, package: str, type_name: str, entry: str) -> None:
self._id = id_val
self._id_package = package
self._id_type = type_name
self._id_entry = entry
def getAutoFillId(self) -> Optional[int]:
return self._id
def setWebDomain(self, domain: str) -> None:
self._web_domain = domain
def getWebDomain(self) -> Optional[str]:
return self._web_domain
def setInputType(self, input_type: int) -> None:
self._input_type = input_type
def getInputType(self) -> int:
return self._input_type
def setAlpha(self, alpha: float) -> None:
self._alpha = max(0.0, min(1.0, alpha))
def getAlpha(self) -> float:
return self._alpha
def setElevation(self, elevation: float) -> None:
self._elevation = elevation
def getElevation(self) -> float:
return self._elevation
def setDimensions(self, width: int, height: int) -> None:
self._width = width
self._height = height
def setDimens(self, left: int, top: int, scroll_x: int, scroll_y: int) -> None:
self._left = left
self._top = top
self._scroll_x = scroll_x
self._scroll_y = scroll_y
def getWidth(self) -> int:
return self._width
def getHeight(self) -> int:
return self._height
def getLeft(self) -> int:
return self._left
def getTop(self) -> int:
return self._top
def addChild(self, num: int) -> ViewStructure:
for _ in range(num):
child = ViewStructure()
self._children.append(child)
return self._children[0] if self._children else ViewStructure()
def getChildCount(self) -> int:
return len(self._children)
def getChildAt(self, index: int) -> Optional[ViewStructure]:
if 0 <= index < len(self._children):
return self._children[index]
return None
def setAutofillHints(self, hints: List[str]) -> None:
pass
def setAutofillType(self, type_val: int) -> None:
pass
def setAutofillValue(self, value: Any) -> None:
pass
def setDataIsSensitive(self, sensitive: bool) -> None:
pass
def toString(self) -> str:
return (f"ViewStructure(class={self._className}, "
f"children={len(self._children)})")
# ═══════════════════════════════════════════════════════════════
# ViewTreeObserver
# ═══════════════════════════════════════════════════════════════
class ViewTreeObserver(Stub):
"""ViewTreeObserver — 视图树观察者"""
def __init__(self):
super().__init__()
self._global_layout_listeners: List[Callable] = []
self._global_focus_listeners: List[Callable] = []
self._pre_draw_listeners: List[Callable] = []
self._scroll_listeners: List[Callable] = []
self._touch_mode_listeners: List[Callable] = []
self._window_focus_listeners: List[Callable] = []
self._window_attach_listeners: List[Callable] = []
self._draw_listeners: List[Callable] = []
self._lock = threading.Lock()
def addOnGlobalLayoutListener(self, listener: Callable) -> None:
with self._lock:
if listener not in self._global_layout_listeners:
self._global_layout_listeners.append(listener)
def removeOnGlobalLayoutListener(self, listener: Callable) -> None:
with self._lock:
if listener in self._global_layout_listeners:
self._global_layout_listeners.remove(listener)
def addOnGlobalFocusChangeListener(self, listener: Callable) -> None:
with self._lock:
if listener not in self._global_focus_listeners:
self._global_focus_listeners.append(listener)
def removeOnGlobalFocusChangeListener(self, listener: Callable) -> None:
with self._lock:
if listener in self._global_focus_listeners:
self._global_focus_listeners.remove(listener)
def addOnPreDrawListener(self, listener: Callable) -> None:
with self._lock:
if listener not in self._pre_draw_listeners:
self._pre_draw_listeners.append(listener)
def removeOnPreDrawListener(self, listener: Callable) -> None:
with self._lock:
if listener in self._pre_draw_listeners:
self._pre_draw_listeners.remove(listener)
def addOnScrollChangedListener(self, listener: Callable) -> None:
with self._lock:
if listener not in self._scroll_listeners:
self._scroll_listeners.append(listener)
def removeOnScrollChangedListener(self, listener: Callable) -> None:
with self._lock:
if listener in self._scroll_listeners:
self._scroll_listeners.remove(listener)
def addOnTouchModeChangeListener(self, listener: Callable) -> None:
with self._lock:
if listener not in self._touch_mode_listeners:
self._touch_mode_listeners.append(listener)
def removeOnTouchModeChangeListener(self, listener: Callable) -> None:
with self._lock:
if listener in self._touch_mode_listeners:
self._touch_mode_listeners.remove(listener)
def addOnWindowFocusChangeListener(self, listener: Callable) -> None:
with self._lock:
if listener not in self._window_focus_listeners:
self._window_focus_listeners.append(listener)
def removeOnWindowFocusChangeListener(self, listener: Callable) -> None:
with self._lock:
if listener in self._window_focus_listeners:
self._window_focus_listeners.remove(listener)
def addOnWindowAttachListener(self, listener: Callable) -> None:
with self._lock:
if listener not in self._window_attach_listeners:
self._window_attach_listeners.append(listener)
def removeOnWindowAttachListener(self, listener: Callable) -> None:
with self._lock:
if listener in self._window_attach_listeners:
self._window_attach_listeners.remove(listener)
def addOnDrawListener(self, listener: Callable) -> None:
with self._lock:
if listener not in self._draw_listeners:
self._draw_listeners.append(listener)
def removeOnDrawListener(self, listener: Callable) -> None:
with self._lock:
if listener in self._draw_listeners:
self._draw_listeners.remove(listener)
def dispatchOnGlobalLayout(self) -> None:
with self._lock:
listeners = list(self._global_layout_listeners)
for listener in listeners:
listener()
def isAlive(self) -> bool:
return True
def toString(self) -> str:
return (f"ViewTreeObserver(layoutListeners={len(self._global_layout_listeners)}, "
f"preDrawListeners={len(self._pre_draw_listeners)})")
# ═══════════════════════════════════════════════════════════════
# ViewDebug
# ═══════════════════════════════════════════════════════════════
class ViewDebug(Stub):
"""ViewDebug — 视图调试工具"""
TRACE_HIERARCHY = 0
TRACE_CAPTURE = 1
@staticmethod
def dump(view: Any, out: Any) -> None:
pass
@staticmethod
def dumpCapturedView(view: Any, out: Any, prefix: str) -> None:
pass
@staticmethod
def trace(view: Any, type_val: int, out: Any) -> None:
pass
@staticmethod
def startRecyclerTracing() -> None:
pass
@staticmethod
def stopRecyclerTracing() -> None:
pass
class RecyclerTraceable(Stub):
def getTraceInfo(self) -> str:
return ""
# ═══════════════════════════════════════════════════════════════
# ViewConfiguration
# ═══════════════════════════════════════════════════════════════
class ViewConfiguration(Stub):
"""ViewConfiguration — 视图配置"""
def __init__(self):
super().__init__()
self._scaled_touch_slop: int = 8
self._scaled_double_tap_slop: int = 100
self._scaled_edge_slop: int = 12
self._scaled_fading_edge_length: int = 12
self._scaled_minimum_fling_velocity: int = 50
self._scaled_maximum_fling_velocity: int = 4000
self._scaled_scroll_bar_size: int = 10
self._scaled_over_scroll_distance: int = 0
self._scaled_paging_touch_slop: int = 16
self._scaled_drawing_cache_size: int = 480
@staticmethod
def get(context: Any) -> "ViewConfiguration":
return ViewConfiguration()
def getScaledTouchSlop(self) -> int:
return self._scaled_touch_slop
def getScaledDoubleTapSlop(self) -> int:
return self._scaled_double_tap_slop
def getScaledEdgeSlop(self) -> int:
return self._scaled_edge_slop
def getScaledFadingEdgeLength(self) -> int:
return self._scaled_fading_edge_length
def getScaledMinimumFlingVelocity(self) -> int:
return self._scaled_minimum_fling_velocity
def getScaledMaximumFlingVelocity(self) -> int:
return self._scaled_maximum_fling_velocity
def getScaledScrollBarSize(self) -> int:
return self._scaled_scroll_bar_size
def getScaledOverScrollDistance(self) -> int:
return self._scaled_over_scroll_distance
def getScaledPagingTouchSlop(self) -> int:
return self._scaled_paging_touch_slop
def getScaledDrawingCacheSize(self) -> int:
return self._scaled_drawing_cache_size
@staticmethod
def getLongPressTimeout() -> int:
return 500
@staticmethod
def getTapTimeout() -> int:
return 100
@staticmethod
def getDoubleTapTimeout() -> int:
return 300
@staticmethod
def getKeyRepeatTimeout() -> int:
return 400
@staticmethod
def getKeyRepeatDelay() -> int:
return 50
@staticmethod
def getScrollDefaultDelay() -> int:
return 40
@staticmethod
def getScrollFriction() -> float:
return 0.015
def toString(self) -> str:
return "ViewConfiguration()"
# ═══════════════════════════════════════════════════════════════
# ViewParent (扩展)
# ═══════════════════════════════════════════════════════════════
class ViewParent(Stub):
"""ViewParent — 视图父容器接口扩展"""
def requestLayout(self) -> None:
pass
def isLayoutRequested(self) -> bool:
return False
def requestTransparentRegion(self, child: Any) -> None:
pass
def invalidateChild(self, child: Any, r: Any) -> None:
pass
def invalidateChildInParent(self, location: Any, r: Any) -> Optional[Any]:
return None
def getParent(self) -> Optional["ViewParent"]:
return None
def requestChildFocus(self, child: Any, focused: Any) -> None:
pass
def recomputeViewAttributes(self, child: Any) -> None:
pass
def clearChildFocus(self, child: Any) -> None:
pass
def getChildVisibleRect(self, child: Any, r: Any, offset: Any) -> bool:
return True
def createSnapshot(self, out: Any, child: Any) -> None:
pass
def onStartTemporaryDetach(self) -> None:
pass
def onFinishTemporaryDetach(self) -> None:
pass
def bringChildToFront(self, child: Any) -> None:
pass
def focusSearch(self, child: Any, direction: int) -> Optional[Any]:
return None
def focusableViewAvailable(self, v: Any) -> None:
pass
def showContextMenuForChild(self, original_view: Any) -> bool:
return False
def actionModeStartingForChild(self, original_view: Any) -> Optional[Any]:
return None
def requestSendAccessibilityEvent(self, child: Any, event: Any) -> bool:
return True
def childHasTransientStateChanged(self, child: Any, has_state: bool) -> None:
pass
def requestChildRectangleOnScreen(self, child: Any, rectangle: Any,
immediate: bool) -> bool:
return True
def canResolveLayoutDirection(self) -> bool:
return True
def isLayoutDirectionResolved(self) -> bool:
return True
def getLayoutDirection(self) -> int:
return 0
def toString(self) -> str:
return "ViewParent()"
# ═══════════════════════════════════════════════════════════════
# ViewGroup (扩展)
# ═══════════════════════════════════════════════════════════════
class ViewGroup(Stub):
"""ViewGroup — 视图组扩展"""
CLIP_TO_PADDING_MASK = 0
FOCUS_AFTER = 1
FOCUS_BEFORE = 2
FOCUS_BLOCK = 3
LAYOUT_MODE_CLIP_BOUNDS = 0
LAYOUT_MODE_OPTICAL_BOUNDS = 1
PERSISTENT_NO_CACHE = 0
PERSISTENT_ANIMATION_CACHE = 1
PERSISTENT_SCROLLING_CACHE = 2
PERSISTENT_ALL_CACHES = 3
class LayoutParams(Stub):
"""ViewGroup.LayoutParams — 布局参数"""
FILL_PARENT = -1
MATCH_PARENT = -1
WRAP_CONTENT = -2
def __init__(self, width: int = WRAP_CONTENT, height: int = WRAP_CONTENT):
super().__init__()
self.width = width
self.height = height
def resolveLayoutDirection(self, layout_direction: int) -> None:
pass
def toString(self) -> str:
return f"LayoutParams({self.width}x{self.height})"
class MarginLayoutParams(LayoutParams):
"""ViewGroup.MarginLayoutParams — 带边距的布局参数"""
def __init__(self, width: int = -2,
height: int = -2):
super().__init__(width, height)
self.leftMargin: int = 0
self.topMargin: int = 0
self.rightMargin: int = 0
self.bottomMargin: int = 0
self.marginStart: int = 0
self.marginEnd: int = 0
def setMargins(self, left: int, top: int, right: int, bottom: int) -> None:
self.leftMargin = left
self.topMargin = top
self.rightMargin = right
self.bottomMargin = bottom
def getMarginLeft(self) -> int:
return self.leftMargin
def getMarginTop(self) -> int:
return self.topMargin
def getMarginRight(self) -> int:
return self.rightMargin
def getMarginBottom(self) -> int:
return self.bottomMargin
def setMarginStart(self, start: int) -> None:
self.marginStart = start
def setMarginEnd(self, end: int) -> None:
self.marginEnd = end
def getMarginStart(self) -> int:
return self.marginStart
def getMarginEnd(self) -> int:
return self.marginEnd
def toString(self) -> str:
return (f"MarginLayoutParams({self.width}x{self.height}, "
f"margins=({self.leftMargin},{self.topMargin},"
f"{self.rightMargin},{self.bottomMargin}))")
def __init__(self):
super().__init__()
self._children: List[Any] = []
self._clip_children = True
self._clip_to_padding = True
self._layout_mode = self.LAYOUT_MODE_CLIP_BOUNDS
self._persistent_caching = self.PERSISTENT_NO_CACHE
self._touch_mode = False
self._motion_event_splitting = True
self._transient_child: Optional[Any] = None
self._add_stateset_focus = False
self._child_drawable_state: Optional[Any] = None
def addView(self, child: Any, index: int = -1) -> None:
if index < 0 or index >= len(self._children):
self._children.append(child)
else:
self._children.insert(index, child)
def removeView(self, child: Any) -> None:
if child in self._children:
self._children.remove(child)
def removeViewAt(self, index: int) -> None:
if 0 <= index < len(self._children):
self._children.pop(index)
def removeAllViews(self) -> None:
self._children.clear()
def getChildCount(self) -> int:
return len(self._children)
def getChildAt(self, index: int) -> Optional[Any]:
if 0 <= index < len(self._children):
return self._children[index]
return None
def indexOfChild(self, child: Any) -> int:
try:
return self._children.index(child)
except ValueError:
return -1
def bringChildToFront(self, child: Any) -> None:
if child in self._children:
self._children.remove(child)
self._children.append(child)
def setClipChildren(self, clip: bool) -> None:
self._clip_children = clip
def getClipChildren(self) -> bool:
return self._clip_children
def setClipToPadding(self, clip: bool) -> None:
self._clip_to_padding = clip
def getClipToPadding(self) -> bool:
return self._clip_to_padding
def setLayoutMode(self, mode: int) -> None:
self._layout_mode = mode
def getLayoutMode(self) -> int:
return self._layout_mode
def setPersistentDrawingCache(self, cache: int) -> None:
self._persistent_caching = cache
def getPersistentDrawingCache(self) -> int:
return self._persistent_caching
def setAddStatesFromChildren(self, add: bool) -> None:
self._add_stateset_focus = add
def addStatesFromChildren(self) -> bool:
return self._add_stateset_focus
def setMotionEventSplittingEnabled(self, split: bool) -> None:
self._motion_event_splitting = split
def isMotionEventSplittingEnabled(self) -> bool:
return self._motion_event_splitting
def setTouchMode(self, touch: bool) -> None:
self._touch_mode = touch
def isTouchMode(self) -> bool:
return self._touch_mode
def onLayout(self, changed: bool, l: int, t: int, r: int, b: int) -> None:
pass
def onInterceptTouchEvent(self, ev: Any) -> bool:
return False
def requestDisallowInterceptTouchEvent(self, disallow: bool) -> None:
pass
def getChildDrawingOrder(self, child_count: int, i: int) -> int:
return i
def setChildrenDrawingOrderEnabled(self, enabled: bool) -> None:
pass
def isChildrenDrawingOrderEnabled(self) -> bool:
return False
def toString(self) -> str:
return f"ViewGroup(children={len(self._children)})"
class ViewGroupOverlay(Stub):
"""ViewGroupOverlay — 视图组覆盖层"""
def __init__(self, host: Any = None):
super().__init__()
self._host = host
self._drawables: List[Any] = []
def add(self, drawable: Any) -> None:
if drawable not in self._drawables:
self._drawables.append(drawable)
def remove(self, drawable: Any) -> None:
if drawable in self._drawables:
self._drawables.remove(drawable)
def clear(self) -> None:
self._drawables.clear()
def toString(self) -> str:
return f"ViewGroupOverlay(size={len(self._drawables)})"
class ViewOverlay(Stub):
"""ViewOverlay — 视图覆盖层"""
def __init__(self, host: Any = None):
super().__init__()
self._host = host
self._drawables: List[Any] = []
def add(self, drawable: Any) -> None:
if drawable not in self._drawables:
self._drawables.append(drawable)
def remove(self, drawable: Any) -> None:
if drawable in self._drawables:
self._drawables.remove(drawable)
def clear(self) -> None:
self._drawables.clear()
def getHost(self) -> Optional[Any]:
return self._host
def toString(self) -> str:
return f"ViewOverlay(size={len(self._drawables)})"
# ═══════════════════════════════════════════════════════════════
# WindowInsets / DisplayCutout / Display
# ═══════════════════════════════════════════════════════════════
class WindowInsets(Stub):
"""WindowInsets — 窗口插入区域"""
def __init__(self):
super().__init__()
self._system_window_insets: Tuple[int, int, int, int] = (0, 0, 0, 0)
self._stable_insets: Tuple[int, int, int, int] = (0, 0, 0, 0)
self._display_cutout_insets: Tuple[int, int, int, int] = (0, 0, 0, 0)
self._mandatory_system_gesture_insets: Tuple[int, int, int, int] = (0, 0, 0, 0)
self._tappable_element_insets: Tuple[int, int, int, int] = (0, 0, 0, 0)
self._system_gesture_insets: Tuple[int, int, int, int] = (0, 0, 0, 0)
self._consume_stable = False
self._consume_system_windows = False
self._display_cutout: Optional[DisplayCutout] = None
self._rounded_corners: List[Any] = []
self._privacy_indicators: Optional[Tuple[int, int, int, int]] = None
def getSystemWindowInsetLeft(self) -> int:
return self._system_window_insets[0]
def getSystemWindowInsetTop(self) -> int:
return self._system_window_insets[1]
def getSystemWindowInsetRight(self) -> int:
return self._system_window_insets[2]
def getSystemWindowInsetBottom(self) -> int:
return self._system_window_insets[3]
def getSystemWindowInsets(self) -> Tuple[int, int, int, int]:
return self._system_window_insets
def getStableInsetLeft(self) -> int:
return self._stable_insets[0]
def getStableInsetTop(self) -> int:
return self._stable_insets[1]
def getStableInsetRight(self) -> int:
return self._stable_insets[2]
def getStableInsetBottom(self) -> int:
return self._stable_insets[3]
def getDisplayCutout(self) -> Optional[DisplayCutout]:
return self._display_cutout
def getDisplayCutoutInsets(self) -> Tuple[int, int, int, int]:
return self._display_cutout_insets
def getMandatorySystemGestureInsets(self) -> Tuple[int, int, int, int]:
return self._mandatory_system_gesture_insets
def getTappableElementInsets(self) -> Tuple[int, int, int, int]:
return self._tappable_element_insets
def getSystemGestureInsets(self) -> Tuple[int, int, int, int]:
return self._system_gesture_insets
def consumeSystemWindowInsets(self) -> WindowInsets:
insets = WindowInsets()
insets._system_window_insets = (0, 0, 0, 0)
return insets
def consumeStableInsets(self) -> WindowInsets:
insets = WindowInsets()
insets._stable_insets = (0, 0, 0, 0)
return insets
def isConsumed(self) -> bool:
return self._consume_system_windows
def hasInsets(self) -> bool:
return (max(self._system_window_insets) > 0 or
max(self._stable_insets) > 0)
def hasSystemWindowInsets(self) -> bool:
return max(self._system_window_insets) > 0
def hasStableInsets(self) -> bool:
return max(self._stable_insets) > 0
def hasDisplayCutout(self) -> bool:
return self._display_cutout is not None
def toString(self) -> str:
return (f"WindowInsets(sys={self._system_window_insets}, "
f"stable={self._stable_insets})")
class DisplayCutout(Stub):
"""DisplayCutout — 屏幕缺口信息"""
def __init__(self):
super().__init__()
self._safe_insets: Tuple[int, int, int, int] = (0, 0, 0, 0)
self._bound_left: Optional[Any] = None
self._bound_top: Optional[Any] = None
self._bound_right: Optional[Any] = None
self._bound_bottom: Optional[Any] = None
self._waterfall_insets: Tuple[int, int, int, int] = (0, 0, 0, 0)
def getSafeInsetLeft(self) -> int:
return self._safe_insets[0]
def getSafeInsetTop(self) -> int:
return self._safe_insets[1]
def getSafeInsetRight(self) -> int:
return self._safe_insets[2]
def getSafeInsetBottom(self) -> int:
return self._safe_insets[3]
def getBoundingRectLeft(self) -> Optional[Any]:
return self._bound_left
def getBoundingRectTop(self) -> Optional[Any]:
return self._bound_top
def getBoundingRectRight(self) -> Optional[Any]:
return self._bound_right
def getBoundingRectBottom(self) -> Optional[Any]:
return self._bound_bottom
def getWaterfallInsets(self) -> Tuple[int, int, int, int]:
return self._waterfall_insets
def toString(self) -> str:
return f"DisplayCutout(safe={self._safe_insets})"
class Display(Stub):
"""Display — 屏幕显示信息"""
DEFAULT_DISPLAY = 0
FLAG_PRESENTATION = 1
FLAG_SECURE = 2
FLAG_SUPPORTS_PROTECTED_BUFFERS = 4
STATE_OFF = 0
STATE_ON = 1
STATE_DOZE = 2
STATE_DOZE_SUSPEND = 3
STATE_SUSPENDED = 4
STATE_UNKNOWN = -1
def __init__(self, display_id: int = DEFAULT_DISPLAY):
super().__init__()
self._display_id = display_id
self._width: int = 1080
self._height: int = 1920
self._refresh_rate: float = 60.0
self._rotation: int = 0
self._state: int = STATE_ON
self._name: str = "Internal Display"
self._flags: int = 0
self._density: float = 2.0
self._dpi_x: float = 480.0
self._dpi_y: float = 480.0
self._app_width: int = 1080
self._app_height: int = 1920
self._smallest_width: int = 1080
self._largest_width: int = 1920
self._hdr_capabilities: Optional[Any] = None
self._mode: Optional[Any] = None
self._supported_modes: List[Any] = []
def getDisplayId(self) -> int:
return self._display_id
def getName(self) -> str:
return self._name
def getFlags(self) -> int:
return self._flags
def getHeight(self) -> int:
return self._height
def getWidth(self) -> int:
return self._width
def getRotation(self) -> int:
return self._rotation
def getState(self) -> int:
return self._state
def getRefreshRate(self) -> float:
return self._refresh_rate
def getDensity(self) -> float:
return self._density
def getDpiX(self) -> float:
return self._dpi_x
def getDpiY(self) -> float:
return self._dpi_y
def getAppWidth(self) -> int:
return self._app_width
def getAppHeight(self) -> int:
return self._app_height
def getSmallestWidth(self) -> int:
return self._smallest_width
def getLargestWidth(self) -> int:
return self._largest_width
def getSupportedModes(self) -> List[Any]:
return list(self._supported_modes)
def getMode(self) -> Optional[Any]:
return self._mode
def isHdr(self) -> bool:
return False
def getHdrCapabilities(self) -> Optional[Any]:
return self._hdr_capabilities
def isValid(self) -> bool:
return True
def toString(self) -> str:
return (f"Display(id={self._display_id}, "
f"{self._width}x{self._height}, "
f"rotation={self._rotation})")
# ═══════════════════════════════════════════════════════════════
# DragEvent / GestureDetector / KeyEvent / KeyCharacterMap
# ═══════════════════════════════════════════════════════════════
DRAG_EVENT_ACTION_DRAG_STARTED = 1
DRAG_EVENT_ACTION_DRAG_ENTERED = 2
DRAG_EVENT_ACTION_DRAG_LOCATION = 3
DRAG_EVENT_ACTION_DRAG_EXITED = 4
DRAG_EVENT_ACTION_DROP = 5
DRAG_EVENT_ACTION_DRAG_ENDED = 6
GESTURE_STATE_NONE = 0
GESTURE_STATE_STARTED = 1
GESTURE_STATE_IN_PROGRESS = 2
GESTURE_STATE_FINISHED = 3
ACTION_DOWN = 0
ACTION_UP = 1
ACTION_MOVE = 2
ACTION_CANCEL = 3
ACTION_OUTSIDE = 4
ACTION_POINTER_DOWN = 5
ACTION_POINTER_UP = 6
ACTION_HOVER_ENTER = 7
ACTION_HOVER_EXIT = 8
ACTION_HOVER_MOVE = 9
ACTION_SCROLL = 10
ACTION_POINTER_INDEX_MASK = 0xFF00
ACTION_POINTER_INDEX_SHIFT = 8
META_ALT_MASK = 2
META_ALT_LEFT_ON = 16
META_ALT_RIGHT_ON = 32
META_ALT_ON = 2
META_CTRL_MASK = 4096
META_CTRL_LEFT_ON = 8192
META_CTRL_RIGHT_ON = 16384
META_CTRL_ON = 4096
META_FUNCTION_ON = 8
META_META_MASK = 65536
META_META_LEFT_ON = 131072
META_META_RIGHT_ON = 262144
META_META_ON = 65536
META_SHIFT_MASK = 1
META_SHIFT_LEFT_ON = 64
META_SHIFT_RIGHT_ON = 128
META_SHIFT_ON = 1
META_SYM_ON = 4
META_CAPS_LOCK_ON = 1048576
META_NUM_LOCK_ON = 2097152
META_SCROLL_LOCK_ON = 4194304
KEYCODE_UNKNOWN = 0
KEYCODE_SOFT_LEFT = 1
KEYCODE_SOFT_RIGHT = 2
KEYCODE_HOME = 3
KEYCODE_BACK = 4
KEYCODE_CALL = 5
KEYCODE_ENDCALL = 6
KEYCODE_0 = 7
KEYCODE_1 = 8
KEYCODE_2 = 9
KEYCODE_3 = 10
KEYCODE_4 = 11
KEYCODE_5 = 12
KEYCODE_6 = 13
KEYCODE_7 = 14
KEYCODE_8 = 15
KEYCODE_9 = 16
KEYCODE_STAR = 17
KEYCODE_POUND = 18
KEYCODE_DPAD_UP = 19
KEYCODE_DPAD_DOWN = 20
KEYCODE_DPAD_LEFT = 21
KEYCODE_DPAD_RIGHT = 22
KEYCODE_DPAD_CENTER = 23
KEYCODE_VOLUME_UP = 24
KEYCODE_VOLUME_DOWN = 25
KEYCODE_POWER = 26
KEYCODE_CAMERA = 27
KEYCODE_CLEAR = 28
KEYCODE_A = 29
KEYCODE_B = 30
KEYCODE_C = 31
KEYCODE_D = 32
KEYCODE_E = 33
KEYCODE_F = 34
KEYCODE_G = 35
KEYCODE_H = 36
KEYCODE_I = 37
KEYCODE_J = 38
KEYCODE_K = 39
KEYCODE_L = 40
KEYCODE_M = 41
KEYCODE_N = 42
KEYCODE_O = 43
KEYCODE_P = 44
KEYCODE_Q = 45
KEYCODE_R = 46
KEYCODE_S = 47
KEYCODE_T = 48
KEYCODE_U = 49
KEYCODE_V = 50
KEYCODE_W = 51
KEYCODE_X = 52
KEYCODE_Y = 53
KEYCODE_Z = 54
KEYCODE_COMMA = 55
KEYCODE_PERIOD = 56
KEYCODE_ALT_LEFT = 57
KEYCODE_ALT_RIGHT = 58
KEYCODE_SHIFT_LEFT = 59
KEYCODE_SHIFT_RIGHT = 60
KEYCODE_TAB = 61
KEYCODE_SPACE = 62
KEYCODE_SYM = 63
KEYCODE_EXPLORER = 64
KEYCODE_ENVELOPE = 65
KEYCODE_ENTER = 66
KEYCODE_DEL = 67
KEYCODE_GRAVE = 68
KEYCODE_MINUS = 69
KEYCODE_EQUALS = 70
KEYCODE_LEFT_BRACKET = 71
KEYCODE_RIGHT_BRACKET = 72
KEYCODE_BACKSLASH = 73
KEYCODE_SEMICOLON = 74
KEYCODE_APOSTROPHE = 75
KEYCODE_SLASH = 76
KEYCODE_AT = 77
KEYCODE_NUM = 78
KEYCODE_HEADSETHOOK = 79
KEYCODE_FOCUS = 80
KEYCODE_PLUS = 81
KEYCODE_MENU = 82
KEYCODE_NOTIFICATION = 83
KEYCODE_SEARCH = 84
KEYCODE_MEDIA_PLAY_PAUSE = 85
KEYCODE_MEDIA_STOP = 86
KEYCODE_MEDIA_NEXT = 87
KEYCODE_MEDIA_PREVIOUS = 88
KEYCODE_MEDIA_REWIND = 89
KEYCODE_MEDIA_FAST_FORWARD = 90
KEYCODE_MUTE = 91
KEYCODE_PAGE_UP = 92
KEYCODE_PAGE_DOWN = 93
KEYCODE_PICTSYMBOLS = 94
KEYCODE_SWITCH_CHARSET = 95
KEYCODE_BUTTON_A = 96
KEYCODE_BUTTON_B = 97
KEYCODE_BUTTON_C = 98
KEYCODE_BUTTON_X = 99
KEYCODE_BUTTON_Y = 100
KEYCODE_BUTTON_Z = 101
KEYCODE_BUTTON_L1 = 102
KEYCODE_BUTTON_R1 = 103
KEYCODE_BUTTON_L2 = 104
KEYCODE_BUTTON_R2 = 105
KEYCODE_BUTTON_THUMBL = 106
KEYCODE_BUTTON_THUMBR = 107
KEYCODE_BUTTON_START = 108
KEYCODE_BUTTON_SELECT = 109
KEYCODE_BUTTON_MODE = 110
KEYCODE_ESCAPE = 111
KEYCODE_FORWARD_DEL = 112
KEYCODE_CTRL_LEFT = 113
KEYCODE_CTRL_RIGHT = 114
KEYCODE_CAPS_LOCK = 115
KEYCODE_SCROLL_LOCK = 116
KEYCODE_META_LEFT = 117
KEYCODE_META_RIGHT = 118
KEYCODE_FUNCTION = 119
KEYCODE_SYSRQ = 120
KEYCODE_BREAK = 121
KEYCODE_MOVE_HOME = 122
KEYCODE_MOVE_END = 123
KEYCODE_INSERT = 124
KEYCODE_FORWARD = 125
KEYCODE_MEDIA_PLAY = 126
KEYCODE_MEDIA_PAUSE = 127
KEYCODE_MEDIA_CLOSE = 128
KEYCODE_MEDIA_EJECT = 129
KEYCODE_MEDIA_RECORD = 130
KEYCODE_F1 = 131
KEYCODE_F2 = 132
KEYCODE_F3 = 133
KEYCODE_F4 = 134
KEYCODE_F5 = 135
KEYCODE_F6 = 136
KEYCODE_F7 = 137
KEYCODE_F8 = 138
KEYCODE_F9 = 139
KEYCODE_F10 = 140
KEYCODE_F11 = 141
KEYCODE_F12 = 142
KEYCODE_NUM_LOCK = 143
KEYCODE_NUMPAD_0 = 144
KEYCODE_NUMPAD_1 = 145
KEYCODE_NUMPAD_2 = 146
KEYCODE_NUMPAD_3 = 147
KEYCODE_NUMPAD_4 = 148
KEYCODE_NUMPAD_5 = 149
KEYCODE_NUMPAD_6 = 150
KEYCODE_NUMPAD_7 = 151
KEYCODE_NUMPAD_8 = 152
KEYCODE_NUMPAD_9 = 153
KEYCODE_NUMPAD_DIVIDE = 154
KEYCODE_NUMPAD_MULTIPLY = 155
KEYCODE_NUMPAD_SUBTRACT = 156
KEYCODE_NUMPAD_ADD = 157
KEYCODE_NUMPAD_DOT = 158
KEYCODE_NUMPAD_COMMA = 159
KEYCODE_NUMPAD_ENTER = 160
KEYCODE_NUMPAD_EQUALS = 161
KEYCODE_NUMPAD_LEFT_PAREN = 162
KEYCODE_NUMPAD_RIGHT_PAREN = 163
KEYCODE_VOLUME_MUTE = 164
KEYCODE_INFO = 165
KEYCODE_CHANNEL_UP = 166
KEYCODE_CHANNEL_DOWN = 167
KEYCODE_ZOOM_IN = 168
KEYCODE_ZOOM_OUT = 169
WINDOW_INSETS_TYPE_SYSTEM_BARS = 0
WINDOW_INSETS_TYPE_STATUS_BARS = 1
WINDOW_INSETS_TYPE_NAVIGATION_BARS = 2
WINDOW_INSETS_TYPE_CAPTION_BAR = 3
WINDOW_INSETS_TYPE_IME = 4
WINDOW_INSETS_TYPE_TAPPABLE_ELEMENT = 5
WINDOW_INSETS_TYPE_MANDATORY_SYSTEM_GESTURES = 6
WINDOW_INSETS_TYPE_SYSTEM_GESTURES = 7
WINDOW_INSETS_TYPE_DISPLAY_CUTOUT = 8
WINDOW_INSETS_TYPE_WATERFALL = 9
WINDOW_INSETS_TYPE_PRIVACY_INDICATORS = 10
WINDOW_INSETS_ANIMATION_TYPE_NONE = 0
WINDOW_INSETS_ANIMATION_TYPE_ALPHA = 1
WINDOW_INSETS_ANIMATION_TYPE_TRANSLATION = 2
WINDOW_INSETS_ANIMATION_TYPE_ALPHA_AND_TRANSLATION = 3
class DragEvent(Stub):
"""DragEvent — 拖放事件"""
ACTION_DRAG_STARTED = DRAG_EVENT_ACTION_DRAG_STARTED
ACTION_DRAG_ENTERED = DRAG_EVENT_ACTION_DRAG_ENTERED
ACTION_DRAG_LOCATION = DRAG_EVENT_ACTION_DRAG_LOCATION
ACTION_DRAG_EXITED = DRAG_EVENT_ACTION_DRAG_EXITED
ACTION_DROP = DRAG_EVENT_ACTION_DROP
ACTION_DRAG_ENDED = DRAG_EVENT_ACTION_DRAG_ENDED
def __init__(self, action: int = 0):
super().__init__()
self._action = action
self._x: float = 0.0
self._y: float = 0.0
self._clip_data: Optional[Any] = None
self._result: Optional[Any] = None
self._local_state: Optional[Any] = None
self._drag_surface: Optional[Any] = None
def getAction(self) -> int:
return self._action
def getX(self) -> float:
return self._x
def getY(self) -> float:
return self._y
def getClipData(self) -> Optional[Any]:
return self._clip_data
def getResult(self) -> Optional[Any]:
return self._result
def getLocalState(self) -> Optional[Any]:
return self._local_state
def toString(self) -> str:
actions = {1: "DRAG_STARTED", 2: "DRAG_ENTERED", 3: "DRAG_LOCATION",
4: "DRAG_EXITED", 5: "DROP", 6: "DRAG_ENDED"}
return f"DragEvent(action={actions.get(self._action, 'UNKNOWN')})"
class GestureDetector(Stub):
"""GestureDetector — 手势检测器"""
class SimpleOnGestureListener(Stub):
"""GestureDetector.SimpleOnGestureListener — 简单手势监听器"""
def onDown(self, e: Any) -> bool:
return False
def onShowPress(self, e: Any) -> None:
pass
def onSingleTapUp(self, e: Any) -> bool:
return False
def onSingleTapConfirmed(self, e: Any) -> bool:
return False
def onDoubleTap(self, e: Any) -> bool:
return False
def onDoubleTapEvent(self, e: Any) -> bool:
return False
def onLongPress(self, e: Any) -> None:
pass
def onScroll(self, e1: Any, e2: Any, distance_x: float, distance_y: float) -> bool:
return False
def onFling(self, e1: Any, e2: Any, velocity_x: float, velocity_y: float) -> bool:
return False
def onContextClick(self, e: Any) -> bool:
return False
class OnGestureListener(Stub):
def onDown(self, e: Any) -> bool:
return False
def onShowPress(self, e: Any) -> None:
pass
def onSingleTapUp(self, e: Any) -> bool:
return False
def onScroll(self, e1: Any, e2: Any, dx: float, dy: float) -> bool:
return False
def onLongPress(self, e: Any) -> None:
pass
def onFling(self, e1: Any, e2: Any, vx: float, vy: float) -> bool:
return False
class OnDoubleTapListener(Stub):
def onSingleTapConfirmed(self, e: Any) -> bool:
return False
def onDoubleTap(self, e: Any) -> bool:
return False
def onDoubleTapEvent(self, e: Any) -> bool:
return False
def onContextClick(self, e: Any) -> bool:
return False
def __init__(self, context: Any = None, listener: Optional[Any] = None):
super().__init__()
self._listener = listener
self._double_tap_listener: Optional[Any] = None
self._is_double_tapping = False
self._touch_slop: int = 8
self._double_tap_slop: int = 100
self._double_tap_timeout: int = 300
self._longpress_timeout: int = 500
self._last_tap_x: float = 0
self._last_tap_y: float = 0
self._last_tap_time: int = 0
def setOnDoubleTapListener(self, listener: Optional[Any]) -> None:
self._double_tap_listener = listener
def setContextClickListener(self, listener: Optional[Any]) -> None:
pass
def setIsLongpressEnabled(self, enabled: bool) -> None:
pass
def isLongpressEnabled(self) -> bool:
return True
def onTouchEvent(self, ev: Any) -> bool:
return True
def toString(self) -> str:
return f"GestureDetector(listener={'yes' if self._listener else 'no'})"
class KeyEvent(Stub):
"""KeyEvent — 按键事件"""
ACTION_DOWN = 0
ACTION_UP = 1
ACTION_MULTIPLE = 2
FLAG_WOKE_HERE = 1
FLAG_SOFT_KEYBOARD = 2
FLAG_KEEP_TOUCH_MODE = 4
FLAG_FROM_SYSTEM = 8
FLAG_EDITOR_ACTION = 16
FLAG_CANCELED = 32
FLAG_VIRTUAL_HARD_KEY = 64
FLAG_LONG_PRESS = 128
FLAG_CANCELED_LONG_PRESS = 256
FLAG_TRACKING = 512
FLAG_FALLBACK = 1024
def __init__(self, action: int = ACTION_DOWN, code: int = KEYCODE_UNKNOWN):
super().__init__()
self._action = action
self._code = code
self._repeat: int = 0
self._meta_state: int = 0
self._device_id: int = 0
self._scan_code: int = 0
self._flags: int = 0
self._down_time: int = 0
self._event_time: int = 0
self._display_id: int = 0
def getAction(self) -> int:
return self._action
def getKeyCode(self) -> int:
return self._code
def getRepeatCount(self) -> int:
return self._repeat
def getMetaState(self) -> int:
return self._meta_state
def getDeviceId(self) -> int:
return self._device_id
def getScanCode(self) -> int:
return self._scan_code
def getFlags(self) -> int:
return self._flags
def getDownTime(self) -> int:
return self._down_time
def getEventTime(self) -> int:
return self._event_time
def getDisplayId(self) -> int:
return self._display_id
def isLongPress(self) -> bool:
return bool(self._flags & self.FLAG_LONG_PRESS)
def isCanceled(self) -> bool:
return bool(self._flags & self.FLAG_CANCELED)
@staticmethod
def isModifierKey(key_code: int) -> bool:
return key_code in (KEYCODE_ALT_LEFT, KEYCODE_ALT_RIGHT,
KEYCODE_SHIFT_LEFT, KEYCODE_SHIFT_RIGHT,
KEYCODE_CTRL_LEFT, KEYCODE_CTRL_RIGHT,
KEYCODE_META_LEFT, KEYCODE_META_RIGHT,
KEYCODE_SYM, KEYCODE_FUNCTION)
@staticmethod
def keyCodeFromString(symbolic_name: str) -> int:
mapping = {
"KEYCODE_A": KEYCODE_A, "KEYCODE_B": KEYCODE_B,
"KEYCODE_C": KEYCODE_C, "KEYCODE_D": KEYCODE_D,
"KEYCODE_E": KEYCODE_E, "KEYCODE_F": KEYCODE_F,
"KEYCODE_G": KEYCODE_G, "KEYCODE_H": KEYCODE_H,
"KEYCODE_I": KEYCODE_I, "KEYCODE_J": KEYCODE_J,
"KEYCODE_K": KEYCODE_K, "KEYCODE_L": KEYCODE_L,
"KEYCODE_M": KEYCODE_M, "KEYCODE_N": KEYCODE_N,
"KEYCODE_O": KEYCODE_O, "KEYCODE_P": KEYCODE_P,
"KEYCODE_Q": KEYCODE_Q, "KEYCODE_R": KEYCODE_R,
"KEYCODE_S": KEYCODE_S, "KEYCODE_T": KEYCODE_T,
"KEYCODE_U": KEYCODE_U, "KEYCODE_V": KEYCODE_V,
"KEYCODE_W": KEYCODE_W, "KEYCODE_X": KEYCODE_X,
"KEYCODE_Y": KEYCODE_Y, "KEYCODE_Z": KEYCODE_Z,
"KEYCODE_0": KEYCODE_0, "KEYCODE_1": KEYCODE_1,
"KEYCODE_2": KEYCODE_2, "KEYCODE_3": KEYCODE_3,
"KEYCODE_4": KEYCODE_4, "KEYCODE_5": KEYCODE_5,
"KEYCODE_6": KEYCODE_6, "KEYCODE_7": KEYCODE_7,
"KEYCODE_8": KEYCODE_8, "KEYCODE_9": KEYCODE_9,
"KEYCODE_HOME": KEYCODE_HOME, "KEYCODE_BACK": KEYCODE_BACK,
"KEYCODE_MENU": KEYCODE_MENU, "KEYCODE_SEARCH": KEYCODE_SEARCH,
"KEYCODE_ENTER": KEYCODE_ENTER, "KEYCODE_DEL": KEYCODE_DEL,
"KEYCODE_SPACE": KEYCODE_SPACE, "KEYCODE_TAB": KEYCODE_TAB,
}
return mapping.get(symbolic_name, KEYCODE_UNKNOWN)
@staticmethod
def keyCodeToString(key_code: int) -> str:
reverse = {v: k for k, v in {
"KEYCODE_A": KEYCODE_A, "KEYCODE_B": KEYCODE_B,
"KEYCODE_HOME": KEYCODE_HOME, "KEYCODE_BACK": KEYCODE_BACK,
}.items()}
return reverse.get(key_code, f"KEYCODE_{key_code}")
def toString(self) -> str:
return (f"KeyEvent(action={self._action}, code={self._code}, "
f"repeat={self._repeat})")
class KeyCharacterMap(Stub):
"""KeyCharacterMap — 按键字符映射"""
ALPHA = 0
FULL = 1
NUMERIC = 2
PREDICTIVE = 3
SPECIAL_FUNCTION = 4
VIRTUAL = 5
BUILT_IN_KEYBOARD = 0
NUMERIC_MODIFIER_MASK = 1
MODIFIER_BEHAVIOR_CHORDED = 0
MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED = 1
def __init__(self):
super().__init__()
def get(self, key_code: int, meta_state: int) -> int:
return 0
def getNumber(self, key_code: int) -> int:
if KEYCODE_0 <= key_code <= KEYCODE_9:
return ord("0") + (key_code - KEYCODE_0)
return 0
def getMatch(self, key_code: int, chars: List[int],
meta_state: int = 0) -> int:
return 0
def getDisplayLabel(self, key_code: int) -> int:
return key_code
def getKeyboardType(self) -> int:
return self.QWERTY
@staticmethod
def deviceHasKey(key_code: int) -> bool:
return True
@staticmethod
def deviceHasKeys(key_codes: List[int]) -> List[bool]:
return [True] * len(key_codes)
def toString(self) -> str:
return "KeyCharacterMap()"
class KeyDispatcherState(Stub):
"""KeyDispatcherState — 按键调度状态"""
def __init__(self):
super().__init__()
self._state: Dict[int, Any] = {}
def reset(self) -> None:
self._state.clear()
def startTracking(self, event: KeyEvent, target: Any) -> None:
key = event.getKeyCode()
self._state[key] = {"target": target, "started": True}
def isTracking(self, event: KeyEvent) -> bool:
key = event.getKeyCode()
return key in self._state and self._state[key].get("started", False)
def performedLongPress(self, event: KeyEvent) -> None:
key = event.getKeyCode()
if key in self._state:
self._state[key]["longpress"] = True
def handleUpEvent(self, event: KeyEvent) -> bool:
key = event.getKeyCode()
if key in self._state:
del self._state[key]
return True
return False
def toString(self) -> str:
return f"KeyDispatcherState(tracking={len(self._state)})"
# ═══════════════════════════════════════════════════════════════
# LayoutInflater / Menu / MenuItem / SubMenu / ContextMenu
# ═══════════════════════════════════════════════════════════════
class LayoutInflater(Stub):
"""LayoutInflater — 布局填充器"""
def __init__(self, context: Any = None):
super().__init__()
self._context = context
@staticmethod
def from_context(context: Any) -> "LayoutInflater":
return LayoutInflater(context)
def inflate(self, resource: Any, root: Any, attach_to_root: bool = False) -> Optional[Any]:
return None
def getContext(self) -> Optional[Any]:
return self._context
def cloneInContext(self, new_context: Any) -> "LayoutInflater":
return LayoutInflater(new_context)
def setFactory(self, factory: Any) -> None:
pass
def getFactory(self) -> Optional[Any]:
return None
def setFactory2(self, factory: Any) -> None:
pass
def getFactory2(self) -> Optional[Any]:
return None
def setFilters(self, filters: List[Any]) -> None:
pass
def toString(self) -> str:
return f"LayoutInflater(context={self._context})"
class Menu(Stub):
"""Menu — 菜单接口"""
FIRST = 1
NONE = 0
CATEGORY_MASK = 0xFFFF
CATEGORY_SHIFT = 16
FLAG_PERFORM_NO_CLOSE = 1
FLAG_ALWAYS_PERFORM_CLOSE = 2
USER_MASK = 0x0000FFFF
USER_SHIFT = 0
CATEGORY_CONTAINER = 0x00010000
CATEGORY_SYSTEM = 0x00020000
CATEGORY_SECONDARY = 0x00030000
CATEGORY_ALTERNATIVE = 0x00040000
CATEGORY_APP = 0x00100000
def add(self, title: str) -> "MenuItem":
return MenuItem(self, 0, 0, 0, title)
def add(self, group_id: int, item_id: int, order: int, title: str) -> "MenuItem":
return MenuItem(self, group_id, item_id, order, title)
def addIntentOptions(self, group_id: int, item_id: int, order: int,
caller: Any, specific: Any, intent: Any,
flags: int, out_specific_items: List[Any]) -> int:
return 0
def addSubMenu(self, title: str) -> "SubMenu":
return SubMenu(self)
def addSubMenu(self, group_id: int, item_id: int, order: int,
title: str) -> "SubMenu":
return SubMenu(self)
def clear(self) -> None:
pass
def removeGroup(self, group_id: int) -> None:
pass
def removeItem(self, id_val: int) -> None:
pass
def setGroupCheckable(self, group: int, checkable: bool,
exclusive: bool) -> None:
pass
def setGroupEnabled(self, group: int, enabled: bool) -> None:
pass
def setGroupVisible(self, group: int, visible: bool) -> None:
pass
def findItem(self, id_val: int) -> Optional["MenuItem"]:
return None
def size(self) -> int:
return 0
def getItem(self, index: int) -> "MenuItem":
return MenuItem(self, 0, 0, 0, "")
def close(self) -> None:
pass
def performIdentifierAction(self, id_val: int, flags: int) -> bool:
return True
def performShortcut(self, key_code: int, event: Any, flags: int) -> bool:
return True
def isShortcutKey(self, key_code: int, event: Any) -> bool:
return False
def hasVisibleItems(self) -> bool:
return False
def onMenuAction(self, id_val: int) -> bool:
return True
def toString(self) -> str:
return "Menu()"
class MenuItem(Stub):
"""MenuItem — 菜单项"""
SHOW_AS_ACTION_ALWAYS = 2
SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8
SHOW_AS_ACTION_IF_ROOM = 1
SHOW_AS_ACTION_NEVER = 0
SHOW_AS_ACTION_WITH_TEXT = 4
def __init__(self, menu: Menu = None, group_id: int = 0,
item_id: int = 0, order: int = 0, title: str = ""):
super().__init__()
self._menu = menu
self._item_id = item_id
self._group_id = group_id
self._order = order
self._title = title
self._title_condensed: Optional[str] = None
self._icon: Optional[Any] = None
self._intent: Optional[Any] = None
self._checked = False
self._checkable = False
self._visible = True
self._enabled = True
self._action_view: Optional[Any] = None
self._on_click: Optional[Callable] = None
self._show_as_action = 0
def getItemId(self) -> int:
return self._item_id
def getGroupId(self) -> int:
return self._group_id
def getOrder(self) -> int:
return self._order
def getTitle(self) -> str:
return self._title
def setTitle(self, title: str) -> "MenuItem":
self._title = title
return self
def getTitleCondensed(self) -> Optional[str]:
return self._title_condensed
def setTitleCondensed(self, title: str) -> "MenuItem":
self._title_condensed = title
return self
def getIcon(self) -> Optional[Any]:
return self._icon
def setIcon(self, icon: Any) -> "MenuItem":
self._icon = icon
return self
def getIntent(self) -> Optional[Any]:
return self._intent
def setIntent(self, intent: Any) -> "MenuItem":
self._intent = intent
return self
def isChecked(self) -> bool:
return self._checked
def setChecked(self, checked: bool) -> "MenuItem":
self._checked = checked
return self
def isCheckable(self) -> bool:
return self._checkable
def setCheckable(self, checkable: bool) -> "MenuItem":
self._checkable = checkable
return self
def isVisible(self) -> bool:
return self._visible
def setVisible(self, visible: bool) -> "MenuItem":
self._visible = visible
return self
def isEnabled(self) -> bool:
return self._enabled
def setEnabled(self, enabled: bool) -> "MenuItem":
self._enabled = enabled
return self
def setOnMenuItemClickListener(self, click: Callable) -> "MenuItem":
self._on_click = click
return self
def getOnMenuItemClickListener(self) -> Optional[Callable]:
return self._on_click
def setActionView(self, view: Any) -> "MenuItem":
self._action_view = view
return self
def setActionView(self, layout_res_id: int) -> "MenuItem":
return self
def getActionView(self) -> Optional[Any]:
return self._action_view
def setShowAsAction(self, action_enum: int) -> None:
self._show_as_action = action_enum
def getShowAsAction(self) -> int:
return self._show_as_action
def expandActionView(self) -> bool:
return True
def collapseActionView(self) -> bool:
return True
def isActionViewExpanded(self) -> bool:
return False
def setOnActionExpandListener(self, listener: Any) -> "MenuItem":
return self
def hasSubMenu(self) -> bool:
return False
def getSubMenu(self) -> Optional["SubMenu"]:
return None
def toString(self) -> str:
return f"MenuItem(id={self._item_id}, title={self._title})"
class SubMenu(Menu):
"""SubMenu — 子菜单"""
def __init__(self, parent: Optional[Menu] = None):
super().__init__()
self._parent = parent
def setHeaderTitle(self, title: str) -> "SubMenu":
return self
def setHeaderIcon(self, icon: Any) -> "SubMenu":
return self
def setHeaderView(self, view: Any) -> "SubMenu":
return self
def clearHeader(self) -> None:
pass
def setIcon(self, icon: Any) -> "SubMenu":
return self
def getItem(self) -> MenuItem:
return MenuItem(self, 0, 0, 0, "")
def toString(self) -> str:
return "SubMenu()"
class ContextMenu(Menu):
"""ContextMenu — 上下文菜单"""
class ContextMenuInfo(Stub):
"""ContextMenu.ContextMenuInfo — 上下文菜单信息接口"""
pass
def __init__(self):
super().__init__()
def setHeaderTitle(self, title: str) -> "ContextMenu":
return self
def setHeaderIcon(self, icon: Any) -> "ContextMenu":
return self
def setHeaderView(self, view: Any) -> "ContextMenu":
return self
def clearHeader(self) -> None:
pass
def toString(self) -> str:
return "ContextMenu()"
# ═══════════════════════════════════════════════════════════════
# ScaleGestureDetector / SoundEffectConstants / Surface / etc.
# ═══════════════════════════════════════════════════════════════
class ScaleGestureDetector(Stub):
"""ScaleGestureDetector — 缩放手势检测器"""
class SimpleOnScaleGestureListener(Stub):
def onScale(self, detector: "ScaleGestureDetector") -> bool:
return False
def onScaleBegin(self, detector: "ScaleGestureDetector") -> bool:
return True
def onScaleEnd(self, detector: "ScaleGestureDetector") -> None:
pass
class OnScaleGestureListener(Stub):
def onScale(self, detector: "ScaleGestureDetector") -> bool:
return False
def onScaleBegin(self, detector: "ScaleGestureDetector") -> bool:
return True
def onScaleEnd(self, detector: "ScaleGestureDetector") -> None:
pass
def __init__(self, context: Any = None, listener: Optional[Any] = None):
super().__init__()
self._listener = listener
self._scale_factor: float = 1.0
self._focus_x: float = 0.0
self._focus_y: float = 0.0
self._current_span: float = 0.0
self._previous_span: float = 0.0
self._time_delta: int = 0
self._in_progress = False
self._quick_scale_enabled = False
def getScaleFactor(self) -> float:
return self._scale_factor
def getFocusX(self) -> float:
return self._focus_x
def getFocusY(self) -> float:
return self._focus_y
def getCurrentSpan(self) -> float:
return self._current_span
def getPreviousSpan(self) -> float:
return self._previous_span
def getCurrentSpanX(self) -> float:
return self._current_span
def getCurrentSpanY(self) -> float:
return self._current_span
def getPreviousSpanX(self) -> float:
return self._previous_span
def getPreviousSpanY(self) -> float:
return self._previous_span
def getTimeDelta(self) -> int:
return self._time_delta
def getEventTime(self) -> int:
return 0
def isInProgress(self) -> bool:
return self._in_progress
def setQuickScaleEnabled(self, enabled: bool) -> None:
self._quick_scale_enabled = enabled
def isQuickScaleEnabled(self) -> bool:
return self._quick_scale_enabled
def onTouchEvent(self, ev: Any) -> bool:
return True
def toString(self) -> str:
return (f"ScaleGestureDetector(scale={self._scale_factor:.2f}, "
f"inProgress={self._in_progress})")
class SoundEffectConstants(Stub):
"""SoundEffectConstants — 音效常量"""
CLICK = 0
NAVIGATION_UP = 1
NAVIGATION_DOWN = 2
NAVIGATION_LEFT = 3
NAVIGATION_RIGHT = 4
NAVIGATION_REPEAT_UP = 5
NAVIGATION_REPEAT_DOWN = 6
NAVIGATION_REPEAT_LEFT = 7
NAVIGATION_REPEAT_RIGHT = 8
@staticmethod
def getContantForFocusDirection(direction: int) -> int:
return SoundEffectConstants.NAVIGATION_UP
class Surface(Stub):
"""Surface — 表面"""
ROTATION_0 = 0
ROTATION_90 = 1
ROTATION_180 = 2
ROTATION_270 = 3
def __init__(self, surface_control: Optional["SurfaceControl"] = None):
super().__init__()
self._surface_control = surface_control
self._is_valid = True
self._width: int = 0
self._height: int = 0
def isValid(self) -> bool:
return self._is_valid
def lockCanvas(self, dirty_rect: Optional[Any] = None) -> Optional[Any]:
return None
def unlockCanvasAndPost(self, canvas: Any) -> None:
pass
def getSurfaceControl(self) -> Optional["SurfaceControl"]:
return self._surface_control
def getWidth(self) -> int:
return self._width
def getHeight(self) -> int:
return self._height
def toString(self) -> str:
return f"Surface(valid={self._is_valid})"
class SurfaceControl(Stub):
"""SurfaceControl — 表面控制"""
BUFFER_TRANSFORM_IDENTITY = 0
BUFFER_TRANSFORM_MIRROR_H = 1
BUFFER_TRANSFORM_MIRROR_V = 2
BUFFER_TRANSFORM_ROTATE_90 = 4
BUFFER_TRANSFORM_ROTATE_180 = 3
BUFFER_TRANSFORM_ROTATE_270 = 7
def __init__(self):
super().__init__()
self._surface: Optional[Surface] = None
self._visible = False
self._alpha: float = 1.0
self._layer: int = 0
def createSurface(self) -> Surface:
self._surface = Surface(self)
return self._surface
def setAlpha(self, alpha: float) -> None:
self._alpha = max(0.0, min(1.0, alpha))
def setLayer(self, layer: int) -> None:
self._layer = layer
def setVisible(self, visible: bool) -> None:
self._visible = visible
def release(self) -> None:
self._surface = None
def toString(self) -> str:
return f"SurfaceControl(layer={self._layer}, visible={self._visible})"
class SurfaceView(Stub):
"""SurfaceView — 表面视图扩展"""
def __init__(self, context: Any = None):
super().__init__()
self._surface: Optional[Surface] = None
self._surface_holder: Optional[Any] = None
self._callback: Optional[Callable] = None
def getHolder(self) -> Optional[Any]:
return self._surface_holder
def getSurfaceControl(self) -> Optional[SurfaceControl]:
return None
def setSecure(self, secure: bool) -> None:
pass
def setZOrderOnTop(self, on_top: bool) -> None:
pass
def setZOrderMediaOverlay(self, is_media_overlay: bool) -> None:
pass
def toString(self) -> str:
return "SurfaceView()"
class TextureView(Stub):
"""TextureView — 纹理视图"""
def __init__(self, context: Any = None):
super().__init__()
self._surface_texture: Optional[Any] = None
self._callback: Optional[Callable] = None
self._update_listener: Optional[Callable] = None
def getSurfaceTexture(self) -> Optional[Any]:
return self._surface_texture
def setSurfaceTextureListener(self, listener: Optional[Callable]) -> None:
self._update_listener = listener
def isAvailable(self) -> bool:
return self._surface_texture is not None
def setOpaque(self, opaque: bool) -> None:
pass
def getBitmap(self) -> Optional[Any]:
return None
def toString(self) -> str:
return "TextureView()"
class TouchDelegate(Stub):
"""TouchDelegate — 触摸委托"""
def __init__(self, bounds: Any, delegate_view: Any):
super().__init__()
self._bounds = bounds
self._delegate_view = delegate_view
self._touch_slop: int = 8
def onTouchEvent(self, event: Any) -> bool:
return False
def toString(self) -> str:
return f"TouchDelegate(delegate={self._delegate_view})"
class VelocityTracker(Stub):
"""VelocityTracker — 速度追踪器"""
def __init__(self, strategy: str = ""):
super().__init__()
self._positions: List[Tuple[float, float, int]] = []
self._strategy = strategy
@staticmethod
def obtain(strategy: str = "") -> "VelocityTracker":
return VelocityTracker(strategy)
def addMovement(self, event: Any) -> None:
pass
def computeCurrentVelocity(self, units: int, max_velocity: float = 10000.0) -> None:
pass
def getXVelocity(self) -> float:
return 0.0
def getYVelocity(self) -> float:
return 0.0
def getXVelocity(self, id_val: int) -> float:
return 0.0
def getYVelocity(self, id_val: int) -> float:
return 0.0
def clear(self) -> None:
self._positions.clear()
def recycle(self) -> None:
self._positions.clear()
def toString(self) -> str:
return f"VelocityTracker(strategy={self._strategy})"
class WindowInsetsAnimation(Stub):
"""WindowInsetsAnimation — 窗口插入动画"""
def __init__(self, type_mask: int = 0, interpolated_fraction: float = 0.0):
super().__init__()
self._type_mask = type_mask
self._interpolated_fraction = interpolated_fraction
self._duration: int = 0
self._interpolator: Optional[Any] = None
def getTypeMask(self) -> int:
return self._type_mask
def getInterpolatedFraction(self) -> float:
return self._interpolated_fraction
def getDurationMillis(self) -> float:
return float(self._duration)
def setDuration(self, duration: int) -> None:
self._duration = duration
def setInterpolator(self, interpolator: Any) -> None:
self._interpolator = interpolator
def getInterpolator(self) -> Optional[Any]:
return self._interpolator
class Callback(Stub):
"""WindowInsetsAnimation.Callback — 动画回调"""
DISPATCH_MODE_STOP = 0
DISPATCH_MODE_CONTINUE_ON_SUBTREE = 1
def __init__(self, dispatch_mode: int = DISPATCH_MODE_CONTINUE_ON_SUBTREE):
super().__init__()
self._dispatch_mode = dispatch_mode
def onPrepare(self, animation: "WindowInsetsAnimation") -> None:
pass
def onStart(self, animation: "WindowInsetsAnimation",
bounds: WindowInsetsAnimation.Bounds) -> None:
pass
def onProgress(self, insets: WindowInsets,
running_animations: List["WindowInsetsAnimation"]) -> WindowInsets:
return insets
def onEnd(self, animation: "WindowInsetsAnimation") -> None:
pass
class Bounds(Stub):
"""WindowInsetsAnimation.Bounds — 动画边界"""
def __init__(self, lower_bound: WindowInsets, upper_bound: WindowInsets):
super().__init__()
self._lower_bound = lower_bound
self._upper_bound = upper_bound
def getLowerBound(self) -> WindowInsets:
return self._lower_bound
def getUpperBound(self) -> WindowInsets:
return self._upper_bound
def inset(self, insets: WindowInsets) -> "Bounds":
return self
def toString(self) -> str:
return "WindowInsetsAnimation.Bounds()"
def toString(self) -> str:
return (f"WindowInsetsAnimation(typeMask={self._type_mask}, "
f"fraction={self._interpolated_fraction})")
class WindowInsetsController(Stub):
"""WindowInsetsController — 窗口插入控制器"""
APPEARANCE_OPAQUE_STATUS_BARS = 1
APPEARANCE_OPAQUE_NAVIGATION_BARS = 2
APPEARANCE_LOW_PROFILE_BARS = 4
APPEARANCE_LIGHT_STATUS_BARS = 8
APPEARANCE_LIGHT_NAVIGATION_BARS = 16
APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS = 32
APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS = 64
BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE = 0
BEHAVIOR_DEFAULT = 1
BEHAVIOR_SHOW_BARS_BY_TOUCH = 2
BEHAVIOR_SHOW_BARS_BY_SWIPE = 3
def __init__(self):
super().__init__()
self._appearance: int = 0
self._behavior: int = self.BEHAVIOR_DEFAULT
self._show_types: int = 0
self._hide_types: int = 0
def show(self, types: int) -> None:
self._show_types |= types
def hide(self, types: int) -> None:
self._hide_types |= types
def setAppearance(self, appearance: int) -> None:
self._appearance = appearance
def getAppearance(self) -> int:
return self._appearance
def setBehavior(self, behavior: int) -> None:
self._behavior = behavior
def getBehavior(self) -> int:
return self._behavior
def setSystemBarsAppearance(self, appearance: int, mask: int) -> None:
self._appearance = (self._appearance & ~mask) | (appearance & mask)
def getSystemBarsAppearance(self) -> int:
return self._appearance
def toString(self) -> str:
return (f"WindowInsetsController(show={self._show_types}, "
f"hide={self._hide_types})")