- 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关键字冲突
2497 lines
74 KiB
Python
2497 lines
74 KiB
Python
"""
|
||
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})") |