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

2198 lines
69 KiB
Python

"""
Android Widget 扩展组件 — AbsoluteLayout, AdapterView, ProgressBar, SeekBar, Layouts 等
方法签名完全对齐 Android SDK
"""
from __future__ import annotations
import math
import time
import threading
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
from .._core import Stub, AndroidOnlyError
from ..java.lang import RuntimeException
# ═══════════════════════════════════════════════════════════════
# 布局常量
# ═══════════════════════════════════════════════════════════════
VISIBLE = 0
INVISIBLE = 4
GONE = 8
MATCH_PARENT = -1
WRAP_CONTENT = -2
FILL_PARENT = -1
HORIZONTAL = 0
VERTICAL = 1
LEFT = 0
RIGHT = 1
CENTER = 2
TOP = 3
BOTTOM = 4
NO_ID = -1
# ═══════════════════════════════════════════════════════════════
# AbsoluteLayout
# ═══════════════════════════════════════════════════════════════
class AbsoluteLayout(Stub):
"""AbsoluteLayout — 绝对布局"""
class LayoutParams(Stub):
"""AbsoluteLayout.LayoutParams — 绝对布局参数"""
def __init__(self, width: int = WRAP_CONTENT, height: int = WRAP_CONTENT,
x: int = 0, y: int = 0):
super().__init__()
self.width = width
self.height = height
self.x = x
self.y = y
def toString(self) -> str:
return (f"AbsoluteLayout.LayoutParams({self.width}x{self.height} "
f"@{self.x},{self.y})")
def __init__(self, context: Any = None):
super().__init__()
self._children: List[Any] = []
def addView(self, child: Any, x: int = 0, y: int = 0) -> None:
self._children.append(child)
def toString(self) -> str:
return f"AbsoluteLayout(children={len(self._children)})"
# ═══════════════════════════════════════════════════════════════
# Adapter / AdapterView / Filter / Filterable
# ═══════════════════════════════════════════════════════════════
class Adapter(Stub):
"""Adapter — 适配器接口"""
IGNORE_ITEM_VIEW_TYPE = -1
NO_SELECTION = -2147483648
def __init__(self):
super().__init__()
self._data_set_observers: List[Callable] = []
def registerDataSetObserver(self, observer: Callable) -> None:
if observer not in self._data_set_observers:
self._data_set_observers.append(observer)
def unregisterDataSetObserver(self, observer: Callable) -> None:
if observer in self._data_set_observers:
self._data_set_observers.remove(observer)
def notifyDataSetChanged(self) -> None:
for obs in list(self._data_set_observers):
obs()
def notifyDataSetInvalidated(self) -> None:
for obs in list(self._data_set_observers):
obs()
def getCount(self) -> int:
return 0
def getItem(self, position: int) -> Optional[Any]:
return None
def getItemId(self, position: int) -> int:
return position
def getItemViewType(self, position: int) -> int:
return Adapter.IGNORE_ITEM_VIEW_TYPE
def getViewTypeCount(self) -> int:
return 1
def hasStableIds(self) -> bool:
return False
def isEmpty(self) -> bool:
return self.getCount() == 0
def getView(self, position: int, convert_view: Optional[Any],
parent: Any) -> Optional[Any]:
return None
def getDropDownView(self, position: int, convert_view: Optional[Any],
parent: Any) -> Optional[Any]:
return self.getView(position, convert_view, parent)
def toString(self) -> str:
return f"Adapter(count={self.getCount()})"
class AdapterView(Stub):
"""AdapterView — 适配器视图"""
ITEM_VIEW_TYPE_IGNORE = -1
ITEM_VIEW_TYPE_HEADER_OR_FOOTER = -2
INVALID_POSITION = -1
INVALID_ROW_ID = -9223372036854775808
INVALID_TYPE = -1
CHOICE_MODE_NONE = 0
CHOICE_MODE_SINGLE = 1
CHOICE_MODE_MULTIPLE = 2
CHOICE_MODE_MODAL = 3
def __init__(self, context: Any = None):
super().__init__()
self._adapter: Optional[Adapter] = None
self._choice_mode: int = self.CHOICE_MODE_NONE
self._checked_positions: Set[int] = set()
self._selected_position: int = self.INVALID_POSITION
self._item_click_listener: Optional[Callable] = None
self._item_long_click_listener: Optional[Callable] = None
self._item_selected_listener: Optional[Callable] = None
self._empty_view: Optional[Any] = None
self._first_visible_position: int = 0
self._last_visible_position: int = 0
self._lock = threading.Lock()
def setAdapter(self, adapter: Optional[Adapter]) -> None:
self._adapter = adapter
def getAdapter(self) -> Optional[Adapter]:
return self._adapter
def setOnItemClickListener(self, listener: Optional[Callable]) -> None:
self._item_click_listener = listener
def getOnItemClickListener(self) -> Optional[Callable]:
return self._item_click_listener
def setOnItemLongClickListener(self, listener: Optional[Callable]) -> None:
self._item_long_click_listener = listener
def setOnItemSelectedListener(self, listener: Optional[Callable]) -> None:
self._item_selected_listener = listener
def getSelectedItemPosition(self) -> int:
return self._selected_position
def getSelectedItemId(self) -> int:
if self._adapter and self._selected_position != self.INVALID_POSITION:
return self._adapter.getItemId(self._selected_position)
return self.INVALID_ROW_ID
def getSelectedView(self) -> Optional[Any]:
return None
def getSelectedItem(self) -> Optional[Any]:
if self._adapter and self._selected_position != self.INVALID_POSITION:
return self._adapter.getItem(self._selected_position)
return None
def setSelection(self, position: int) -> None:
self._selected_position = position
def getFirstVisiblePosition(self) -> int:
return self._first_visible_position
def getLastVisiblePosition(self) -> int:
return self._last_visible_position
def getCount(self) -> int:
return self._adapter.getCount() if self._adapter else 0
def getChildAt(self, index: int) -> Optional[Any]:
return None
def getChildCount(self) -> int:
return 0
def setChoiceMode(self, mode: int) -> None:
self._choice_mode = mode
def getChoiceMode(self) -> int:
return self._choice_mode
def setItemChecked(self, position: int, checked: bool) -> None:
with self._lock:
if checked:
if self._choice_mode == self.CHOICE_MODE_SINGLE:
self._checked_positions.clear()
self._checked_positions.add(position)
else:
self._checked_positions.discard(position)
def isItemChecked(self, position: int) -> bool:
return position in self._checked_positions
def getCheckedItemPosition(self) -> int:
if self._checked_positions:
return next(iter(self._checked_positions))
return self.INVALID_POSITION
def getCheckedItemPositions(self) -> Set[int]:
return set(self._checked_positions)
def getCheckedItemIds(self) -> Set[int]:
ids = set()
for pos in self._checked_positions:
if self._adapter:
ids.add(self._adapter.getItemId(pos))
return ids
def getCheckItemCount(self) -> int:
return len(self._checked_positions)
def setEmptyView(self, view: Any) -> None:
self._empty_view = view
def getEmptyView(self) -> Optional[Any]:
return self._empty_view
def performItemClick(self, view: Any, position: int, id_val: int) -> bool:
if self._item_click_listener:
self._item_click_listener(self, view, position, id_val)
return True
return False
def toString(self) -> str:
return (f"AdapterView(adapter={'yes' if self._adapter else 'no'}, "
f"count={self.getCount()})")
class Filter(Stub):
"""Filter — 过滤器"""
class FilterResults(Stub):
"""Filter.FilterResults — 过滤结果"""
def __init__(self):
super().__init__()
self.values: Optional[Any] = None
self.count: int = 0
def __init__(self):
super().__init__()
self._filter_listener: Optional[Callable] = None
def filter(self, constraint: str) -> None:
results = self.performFiltering(constraint)
self.publishResults(constraint, results)
def filter(self, constraint: str, listener: Optional[Callable]) -> None:
self._filter_listener = listener
self.filter(constraint)
def performFiltering(self, constraint: str) -> FilterResults:
return Filter.FilterResults()
def publishResults(self, constraint: str, results: FilterResults) -> None:
pass
def convertResultToString(self, result_value: Any) -> str:
return str(result_value) if result_value is not None else ""
def toString(self) -> str:
return "Filter()"
class Filterable(Stub):
"""Filterable — 可过滤接口"""
def getFilter(self) -> Filter:
return Filter()
class ThemedSpinnerAdapter(Stub):
"""ThemedSpinnerAdapter — 主题化 Spinner 适配器"""
def setDropDownViewTheme(self, theme: Any) -> None:
pass
def getDropDownViewTheme(self) -> Optional[Any]:
return None
# ═══════════════════════════════════════════════════════════════
# AutoCompleteTextView
# ═══════════════════════════════════════════════════════════════
class AutoCompleteTextView(Stub):
"""AutoCompleteTextView — 自动完成文本视图"""
THRESHOLD_DEFAULT = 2
def __init__(self, context: Any = None):
super().__init__()
self._threshold = self.THRESHOLD_DEFAULT
self._adapter: Optional[Adapter] = None
self._listener: Optional[Callable] = None
self._validator: Optional[Callable] = None
self._completion_hint: Optional[str] = None
self._drop_down_width: int = WRAP_CONTENT
self._drop_down_height: int = WRAP_CONTENT
self._drop_down_anchor: Optional[Any] = None
self._drop_down_horizontal_offset: int = 0
self._drop_down_vertical_offset: int = 0
self._showing = False
def setThreshold(self, threshold: int) -> None:
self._threshold = max(1, threshold)
def getThreshold(self) -> int:
return self._threshold
def setAdapter(self, adapter: Adapter) -> None:
self._adapter = adapter
def getAdapter(self) -> Optional[Adapter]:
return self._adapter
def setOnItemClickListener(self, listener: Optional[Callable]) -> None:
self._listener = listener
def setOnItemSelectedListener(self, listener: Optional[Callable]) -> None:
pass
def showDropDown(self) -> None:
self._showing = True
def dismissDropDown(self) -> None:
self._showing = False
def isShowing(self) -> bool:
return self._showing
def setDropDownWidth(self, width: int) -> None:
self._drop_down_width = width
def getDropDownWidth(self) -> int:
return self._drop_down_width
def setDropDownHeight(self, height: int) -> None:
self._drop_down_height = height
def getDropDownHeight(self) -> int:
return self._drop_down_height
def setDropDownAnchor(self, anchor: Any) -> None:
self._drop_down_anchor = anchor
def getDropDownAnchor(self) -> Optional[Any]:
return self._drop_down_anchor
def setDropDownHorizontalOffset(self, offset: int) -> None:
self._drop_down_horizontal_offset = offset
def getDropDownHorizontalOffset(self) -> int:
return self._drop_down_horizontal_offset
def setDropDownVerticalOffset(self, offset: int) -> None:
self._drop_down_vertical_offset = offset
def getDropDownVerticalOffset(self) -> int:
return self._drop_down_vertical_offset
def setCompletionHint(self, hint: str) -> None:
self._completion_hint = hint
def getCompletionHint(self) -> Optional[str]:
return self._completion_hint
def setValidator(self, validator: Optional[Callable]) -> None:
self._validator = validator
def getValidator(self) -> Optional[Callable]:
return self._validator
def performValidation(self) -> None:
if self._validator:
self._validator()
def enoughToFilter(self) -> bool:
return True
def toString(self) -> str:
return f"AutoCompleteTextView(threshold={self._threshold})"
# ═══════════════════════════════════════════════════════════════
# ProgressBar / SeekBar / AbsSeekBar / RatingBar
# ═══════════════════════════════════════════════════════════════
class ProgressBar(Stub):
"""ProgressBar — 进度条扩展"""
STYLE_HORIZONTAL = 0x00000001
STYLE_SPINNER = 0x00000000
def __init__(self, context: Any = None, style: int = STYLE_SPINNER):
super().__init__()
self._min: int = 0
self._max: int = 100
self._progress: int = 0
self._secondary_progress: int = 0
self._indeterminate = (style == self.STYLE_SPINNER)
self._indeterminate_drawable: Optional[Any] = None
self._progress_drawable: Optional[Any] = None
self._on_progress_listener: Optional[Callable] = None
self._mirror = False
def setMin(self, min_val: int) -> None:
self._min = min_val
if self._progress < min_val:
self._progress = min_val
def getMin(self) -> int:
return self._min
def setMax(self, max_val: int) -> None:
self._max = max_val
if self._progress > max_val:
self._progress = max_val
def getMax(self) -> int:
return self._max
def setProgress(self, progress: int) -> None:
self._progress = max(self._min, min(self._max, progress))
if self._on_progress_listener:
self._on_progress_listener(self, self._progress)
def getProgress(self) -> int:
return self._progress
def setSecondaryProgress(self, progress: int) -> None:
self._secondary_progress = max(self._min, min(self._max, progress))
def getSecondaryProgress(self) -> int:
return self._secondary_progress
def incrementProgressBy(self, diff: int) -> None:
self.setProgress(self._progress + diff)
def incrementSecondaryProgressBy(self, diff: int) -> None:
self._secondary_progress = max(self._min, min(self._max, self._secondary_progress + diff))
def setIndeterminate(self, indeterminate: bool) -> None:
self._indeterminate = indeterminate
def isIndeterminate(self) -> bool:
return self._indeterminate
def setIndeterminateDrawable(self, drawable: Any) -> None:
self._indeterminate_drawable = drawable
def getIndeterminateDrawable(self) -> Optional[Any]:
return self._indeterminate_drawable
def setProgressDrawable(self, drawable: Any) -> None:
self._progress_drawable = drawable
def getProgressDrawable(self) -> Optional[Any]:
return self._progress_drawable
def setOnProgressBarChangeListener(self, listener: Optional[Callable]) -> None:
self._on_progress_listener = listener
def setMirrorForRtl(self, mirror: bool) -> None:
self._mirror = mirror
def getMirrorForRtl(self) -> bool:
return self._mirror
def getProgressScale(self) -> float:
if self._max <= self._min:
return 0.0
return (self._progress - self._min) / (self._max - self._min)
def toString(self) -> str:
return (f"ProgressBar(min={self._min}, max={self._max}, "
f"progress={self._progress}, "
f"indeterminate={self._indeterminate})")
class AbsSeekBar(ProgressBar):
"""AbsSeekBar — 抽象进度条"""
def __init__(self, context: Any = None):
super().__init__(context, ProgressBar.STYLE_HORIZONTAL)
self._thumb: Optional[Any] = None
self._thumb_offset: int = 0
self._key_progress_increment: int = 1
self._is_dragging = False
self._on_seek_bar_change: Optional[Callable] = None
self._split_track: bool = False
self._tick_mark: Optional[Any] = None
def setThumb(self, thumb: Any) -> None:
self._thumb = thumb
def getThumb(self) -> Optional[Any]:
return self._thumb
def setThumbOffset(self, offset: int) -> None:
self._thumb_offset = offset
def getThumbOffset(self) -> int:
return self._thumb_offset
def setKeyProgressIncrement(self, increment: int) -> None:
self._key_progress_increment = max(1, increment)
def getKeyProgressIncrement(self) -> int:
return self._key_progress_increment
def setSplitTrack(self, split: bool) -> None:
self._split_track = split
def getSplitTrack(self) -> bool:
return self._split_track
def setTickMark(self, mark: Any) -> None:
self._tick_mark = mark
def getTickMark(self) -> Optional[Any]:
return self._tick_mark
def setOnSeekBarChangeListener(self, listener: Optional[Callable]) -> None:
self._on_seek_bar_change = listener
class SeekBar(AbsSeekBar):
"""SeekBar — 拖动条"""
def __init__(self, context: Any = None):
super().__init__(context)
self._on_seek_bar_change: Optional[Callable] = None
def setOnSeekBarChangeListener(self, listener: Optional[Callable]) -> None:
self._on_seek_bar_change = listener
def getOnSeekBarChangeListener(self) -> Optional[Callable]:
return self._on_seek_bar_change
def toString(self) -> str:
return f"SeekBar(progress={self.getProgress()})"
class RatingBar(ProgressBar):
"""RatingBar — 评分条"""
def __init__(self, context: Any = None, num_stars: int = 5,
step_size: float = 0.5):
super().__init__(context, ProgressBar.STYLE_HORIZONTAL)
self._num_stars = num_stars
self._step_size = step_size
self._rating: float = 0.0
self._is_indicator = False
self._on_rating_change: Optional[Callable] = None
self.setMax(num_stars)
def setNumStars(self, num: int) -> None:
self._num_stars = num
self.setMax(num)
def getNumStars(self) -> int:
return self._num_stars
def setRating(self, rating: float) -> None:
self._rating = max(0.0, min(float(self._num_stars), rating))
self.setProgress(int(self._rating))
def getRating(self) -> float:
return self._rating
def setStepSize(self, size: float) -> None:
self._step_size = max(0.1, size)
def getStepSize(self) -> float:
return self._step_size
def setIsIndicator(self, indicator: bool) -> None:
self._is_indicator = indicator
def isIndicator(self) -> bool:
return self._is_indicator
def setOnRatingBarChangeListener(self, listener: Optional[Callable]) -> None:
self._on_rating_change = listener
def getOnRatingBarChangeListener(self) -> Optional[Callable]:
return self._on_rating_change
def toString(self) -> str:
return f"RatingBar(rating={self._rating}/{self._num_stars})"
# ═══════════════════════════════════════════════════════════════
# Chronometer
# ═══════════════════════════════════════════════════════════════
class Chronometer(Stub):
"""Chronometer — 计时器"""
FORMAT_ELAPSED_TIME = 1
FORMAT_SECONDS = 2
FORMAT_MINUTES = 3
def __init__(self, context: Any = None):
super().__init__()
self._base: int = 0
self._elapsed: int = 0
self._running = False
self._format: str = "%H:%M:%S"
self._on_tick: Optional[Callable] = None
self._lock = threading.Lock()
def setBase(self, base: int) -> None:
self._base = base
def getBase(self) -> int:
return self._base
def start(self) -> None:
with self._lock:
self._running = True
def stop(self) -> None:
with self._lock:
self._running = False
self._elapsed = int(time.time() * 1000) - self._base
def setFormat(self, format_str: str) -> None:
self._format = format_str
def getFormat(self) -> str:
return self._format
def setOnChronometerTickListener(self, listener: Optional[Callable]) -> None:
self._on_tick = listener
def getOnChronometerTickListener(self) -> Optional[Callable]:
return self._on_tick
def isRunning(self) -> bool:
return self._running
def getElapsedTime(self) -> int:
if self._running:
return int(time.time() * 1000) - self._base
return self._elapsed
def toString(self) -> str:
return f"Chronometer(running={self._running})"
# ═══════════════════════════════════════════════════════════════
# CompoundButton / ToggleButton / RadioButton / RadioGroup
# ═══════════════════════════════════════════════════════════════
class CompoundButton(Stub):
"""CompoundButton — 复合按钮"""
def __init__(self, context: Any = None):
super().__init__()
self._checked = False
self._on_check_listener: Optional[Callable] = None
self._button_drawable: Optional[Any] = None
def toggle(self) -> None:
self.setChecked(not self._checked)
def setChecked(self, checked: bool) -> None:
if self._checked != checked:
self._checked = checked
if self._on_check_listener:
self._on_check_listener(self, checked)
def isChecked(self) -> bool:
return self._checked
def setOnCheckedChangeListener(self, listener: Optional[Callable]) -> None:
self._on_check_listener = listener
def getOnCheckedChangeListener(self) -> Optional[Callable]:
return self._on_check_listener
def setButtonDrawable(self, drawable: Any) -> None:
self._button_drawable = drawable
def getButtonDrawable(self) -> Optional[Any]:
return self._button_drawable
def toString(self) -> str:
return f"CompoundButton(checked={self._checked})"
class ToggleButton(CompoundButton):
"""ToggleButton — 开关按钮"""
def __init__(self, context: Any = None):
super().__init__(context)
self._text_on: str = "ON"
self._text_off: str = "OFF"
def setTextOn(self, text: str) -> None:
self._text_on = text
def getTextOn(self) -> str:
return self._text_on
def setTextOff(self, text: str) -> None:
self._text_off = text
def getTextOff(self) -> str:
return self._text_off
def toString(self) -> str:
return f"ToggleButton(checked={self.isChecked()})"
class RadioButton(CompoundButton):
"""RadioButton — 单选按钮"""
def __init__(self, context: Any = None):
super().__init__(context)
def toggle(self) -> None:
if not self.isChecked():
super().toggle()
def toString(self) -> str:
return f"RadioButton(checked={self.isChecked()})"
class RadioGroup(Stub):
"""RadioGroup — 单选按钮组"""
class LayoutParams(Stub):
"""RadioGroup.LayoutParams — 单选按钮组布局参数"""
def __init__(self, width: int = WRAP_CONTENT, height: int = WRAP_CONTENT):
super().__init__()
self.width = width
self.height = height
def toString(self) -> str:
return f"RadioGroup.LayoutParams({self.width}x{self.height})"
def __init__(self, context: Any = None):
super().__init__()
self._checked_id: int = NO_ID
self._on_check_listener: Optional[Callable] = None
self._children: List[RadioButton] = []
self._protect_from_checked_change = False
def setOnCheckedChangeListener(self, listener: Optional[Callable]) -> None:
self._on_check_listener = listener
def getOnCheckedChangeListener(self) -> Optional[Callable]:
return self._on_check_listener
def check(self, id_val: int) -> None:
self._checked_id = id_val
if self._on_check_listener:
self._on_check_listener(self, id_val)
def getCheckedRadioButtonId(self) -> int:
return self._checked_id
def clearCheck(self) -> None:
self._checked_id = NO_ID
def addView(self, child: RadioButton, index: int = -1) -> None:
if index < 0 or index >= len(self._children):
self._children.append(child)
else:
self._children.insert(index, child)
def getChildCount(self) -> int:
return len(self._children)
def toString(self) -> str:
return f"RadioGroup(checkedId={self._checked_id})"
# ═══════════════════════════════════════════════════════════════
# TableLayout / TableRow
# ═══════════════════════════════════════════════════════════════
class TableLayout(Stub):
"""TableLayout — 表格布局"""
def __init__(self, context: Any = None):
super().__init__()
self._rows: List[TableRow] = []
self._columns_stretchable: Set[int] = set()
self._columns_collapsible: Set[int] = set()
self._shrink_allowed = False
self._stretch_allowed = False
def addView(self, child: Any, index: int = -1) -> None:
pass
def setColumnStretchable(self, column_index: int, stretchable: bool) -> None:
if stretchable:
self._columns_stretchable.add(column_index)
else:
self._columns_stretchable.discard(column_index)
def setColumnCollapsible(self, column_index: int, collapsible: bool) -> None:
if collapsible:
self._columns_collapsible.add(column_index)
else:
self._columns_collapsible.discard(column_index)
def setShrinkAllColumns(self, shrink: bool) -> None:
self._shrink_allowed = shrink
def setStretchAllColumns(self, stretch: bool) -> None:
self._stretch_allowed = stretch
def toString(self) -> str:
return f"TableLayout(rows={len(self._rows)})"
class TableRow(Stub):
"""TableRow — 表格行"""
class LayoutParams(Stub):
"""TableRow.LayoutParams — 行布局参数"""
def __init__(self, width: int = MATCH_PARENT, height: int = WRAP_CONTENT):
super().__init__()
self.width = width
self.height = height
self.column: int = -1
self.span: int = 1
def toString(self) -> str:
return f"TableRow.LayoutParams(col={self.column}, span={self.span})"
def __init__(self, context: Any = None):
super().__init__()
self._children: List[Any] = []
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 getChildCount(self) -> int:
return len(self._children)
def getVirtualChildAt(self, index: int) -> Optional[Any]:
if 0 <= index < len(self._children):
return self._children[index]
return None
def toString(self) -> str:
return f"TableRow(children={len(self._children)})"
# ═══════════════════════════════════════════════════════════════
# GridLayout
# ═══════════════════════════════════════════════════════════════
class GridLayout(Stub):
"""GridLayout — 网格布局"""
class Alignment(Stub):
"""GridLayout.Alignment — 对齐方式"""
def __init__(self, name: str = ""):
super().__init__()
self._name = name
def toString(self) -> str:
return f"Alignment({self._name})"
FILL = Alignment("FILL")
CENTER = Alignment("CENTER")
LEFT = Alignment("LEFT")
RIGHT = Alignment("RIGHT")
TOP = Alignment("TOP")
BOTTOM = Alignment("BOTTOM")
BASELINE = Alignment("BASELINE")
START = Alignment("START")
END = Alignment("END")
ALIGN_BOUNDS = 0
ALIGN_MARGINS = 1
HORIZONTAL = 0
VERTICAL = 1
UNDEFINED = -2147483648
class Spec(Stub):
"""GridLayout.Spec — 网格规格"""
def __init__(self, start: int = -2147483648, span: int = 1,
alignment: Optional["GridLayout.Alignment"] = None):
super().__init__()
self.start = start
self.span = span
self.alignment = alignment
def toString(self) -> str:
return f"Spec(start={self.start}, span={self.span})"
class LayoutParams(Stub):
"""GridLayout.LayoutParams — 网格布局参数"""
def __init__(self):
super().__init__()
self.width = WRAP_CONTENT
self.height = WRAP_CONTENT
self.columnSpec = GridLayout.Spec(GridLayout.UNDEFINED, 1, GridLayout.FILL)
self.rowSpec = GridLayout.Spec(GridLayout.UNDEFINED, 1, GridLayout.FILL)
self.setMargins(0, 0, 0, 0)
self.leftMargin = 0
self.topMargin = 0
self.rightMargin = 0
self.bottomMargin = 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 setGravity(self, gravity: int) -> None:
pass
def toString(self) -> str:
return (f"GridLayout.LayoutParams(col={self.columnSpec}, "
f"row={self.rowSpec})")
@staticmethod
def spec(start: int = UNDEFINED, span: int = 1,
alignment: Optional[Alignment] = None) -> Spec:
return GridLayout.Spec(start, span, alignment)
def __init__(self, context: Any = None):
super().__init__()
self._orientation = self.HORIZONTAL
self._column_count: int = 2
self._row_count: int = 2
self._alignment_mode = self.ALIGN_BOUNDS
self._use_default_margins = False
self._children: List[Any] = []
def setOrientation(self, orientation: int) -> None:
self._orientation = orientation
def getOrientation(self) -> int:
return self._orientation
def setColumnCount(self, count: int) -> None:
self._column_count = max(0, count)
def getColumnCount(self) -> int:
return self._column_count
def setRowCount(self, count: int) -> None:
self._row_count = max(0, count)
def getRowCount(self) -> int:
return self._row_count
def setAlignmentMode(self, mode: int) -> None:
self._alignment_mode = mode
def getAlignmentMode(self) -> int:
return self._alignment_mode
def setUseDefaultMargins(self, use: bool) -> None:
self._use_default_margins = use
def getUseDefaultMargins(self) -> bool:
return self._use_default_margins
def toString(self) -> str:
return f"GridLayout({self._column_count}x{self._row_count})"
# ═══════════════════════════════════════════════════════════════
# LinearLayout / FrameLayout / RelativeLayout
# ═══════════════════════════════════════════════════════════════
class LinearLayout(Stub):
"""LinearLayout — 线性布局"""
HORIZONTAL = 0
VERTICAL = 1
SHOW_DIVIDER_NONE = 0
SHOW_DIVIDER_BEGINNING = 1
SHOW_DIVIDER_MIDDLE = 2
SHOW_DIVIDER_END = 4
class LayoutParams(Stub):
"""LinearLayout.LayoutParams — 线性布局参数"""
def __init__(self, width: int = MATCH_PARENT, height: int = WRAP_CONTENT,
weight: float = 0.0):
super().__init__()
self.width = width
self.height = height
self.weight = weight
self.gravity = -1
self.leftMargin = 0
self.topMargin = 0
self.rightMargin = 0
self.bottomMargin = 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 toString(self) -> str:
return (f"LinearLayout.LayoutParams({self.width}x{self.height}, "
f"weight={self.weight})")
def __init__(self, context: Any = None):
super().__init__()
self._orientation = self.HORIZONTAL
self._weight_sum: float = 0.0
self._baseline_aligned = True
self._divider: Optional[Any] = None
self._divider_padding: int = 0
self._show_dividers = self.SHOW_DIVIDER_NONE
self._gravity: int = -1
def setOrientation(self, orientation: int) -> None:
self._orientation = orientation
def getOrientation(self) -> int:
return self._orientation
def setWeightSum(self, weight_sum: float) -> None:
self._weight_sum = weight_sum
def getWeightSum(self) -> float:
return self._weight_sum
def setBaselineAligned(self, aligned: bool) -> None:
self._baseline_aligned = aligned
def isBaselineAligned(self) -> bool:
return self._baseline_aligned
def setDividerDrawable(self, divider: Any) -> None:
self._divider = divider
def getDividerDrawable(self) -> Optional[Any]:
return self._divider
def setDividerPadding(self, padding: int) -> None:
self._divider_padding = padding
def getDividerPadding(self) -> int:
return self._divider_padding
def setShowDividers(self, show: int) -> None:
self._show_dividers = show
def getShowDividers(self) -> int:
return self._show_dividers
def setGravity(self, gravity: int) -> None:
self._gravity = gravity
def getGravity(self) -> int:
return self._gravity
def toString(self) -> str:
return f"LinearLayout(orientation={'H' if self._orientation == 0 else 'V'})"
class FrameLayout(Stub):
"""FrameLayout — 帧布局"""
class LayoutParams(Stub):
"""FrameLayout.LayoutParams — 帧布局参数"""
UNSPECIFIED_GRAVITY = -1
def __init__(self, width: int = MATCH_PARENT, height: int = MATCH_PARENT,
gravity: int = UNSPECIFIED_GRAVITY):
super().__init__()
self.width = width
self.height = height
self.gravity = gravity
self.leftMargin = 0
self.topMargin = 0
self.rightMargin = 0
self.bottomMargin = 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 toString(self) -> str:
return (f"FrameLayout.LayoutParams({self.width}x{self.height}, "
f"gravity={self.gravity})")
def __init__(self, context: Any = None):
super().__init__()
self._foreground: Optional[Any] = None
self._foreground_gravity: int = 0
self._measure_all_children = False
def setForeground(self, drawable: Any) -> None:
self._foreground = drawable
def getForeground(self) -> Optional[Any]:
return self._foreground
def setForegroundGravity(self, gravity: int) -> None:
self._foreground_gravity = gravity
def getForegroundGravity(self) -> int:
return self._foreground_gravity
def setMeasureAllChildren(self, measure: bool) -> None:
self._measure_all_children = measure
def getMeasureAllChildren(self) -> bool:
return self._measure_all_children
def toString(self) -> str:
return "FrameLayout()"
class RelativeLayout(Stub):
"""RelativeLayout — 相对布局"""
TRUE = -1
FALSE = -2
ALIGN_PARENT_LEFT = 1
ALIGN_PARENT_TOP = 2
ALIGN_PARENT_RIGHT = 4
ALIGN_PARENT_BOTTOM = 8
ALIGN_PARENT_START = 16
ALIGN_PARENT_END = 32
CENTER_IN_PARENT = 64
CENTER_HORIZONTAL = 128
CENTER_VERTICAL = 256
ABOVE = 512
BELOW = 1024
LEFT_OF = 2048
RIGHT_OF = 4096
ALIGN_LEFT = 8192
ALIGN_TOP = 16384
ALIGN_RIGHT = 32768
ALIGN_BOTTOM = 65536
ALIGN_BASELINE = 131072
ALIGN_START = 262144
ALIGN_END = 524288
START_OF = 1048576
END_OF = 2097152
LAYOUT_DIRECTION = 4194304
class LayoutParams(Stub):
"""RelativeLayout.LayoutParams — 相对布局参数"""
def __init__(self, width: int = WRAP_CONTENT, height: int = WRAP_CONTENT):
super().__init__()
self.width = width
self.height = height
self.leftMargin = 0
self.topMargin = 0
self.rightMargin = 0
self.bottomMargin = 0
self.marginStart = 0
self.marginEnd = 0
self._rules: Dict[int, int] = {}
self._align_with_parent = False
def addRule(self, verb: int, subject: int = -1) -> None:
self._rules[verb] = subject
def removeRule(self, verb: int) -> None:
self._rules.pop(verb, None)
def getRule(self, verb: int) -> int:
return self._rules.get(verb, 0)
def getRules(self) -> Dict[int, int]:
return dict(self._rules)
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 setMarginStart(self, start: int) -> None:
self.marginStart = start
def setMarginEnd(self, end: int) -> None:
self.marginEnd = end
def toString(self) -> str:
return (f"RelativeLayout.LayoutParams({self.width}x{self.height}, "
f"rules={len(self._rules)})")
def __init__(self, context: Any = None):
super().__init__()
self._gravity: int = -1
self._horizontal_gravity: int = -1
self._vertical_gravity: int = -1
self._ignore_gravity = False
def setGravity(self, gravity: int) -> None:
self._gravity = gravity
def getGravity(self) -> int:
return self._gravity
def setHorizontalGravity(self, gravity: int) -> None:
self._horizontal_gravity = gravity
def setVerticalGravity(self, gravity: int) -> None:
self._vertical_gravity = gravity
def setIgnoreGravity(self, view_id: int) -> None:
self._ignore_gravity = True
def getIgnoreGravity(self) -> int:
return 0
def toString(self) -> str:
return "RelativeLayout()"
# ═══════════════════════════════════════════════════════════════
# NumberPicker / SearchView / TabHost / TabWidget
# ═══════════════════════════════════════════════════════════════
class NumberPicker(Stub):
"""NumberPicker — 数字选择器"""
def __init__(self, context: Any = None):
super().__init__()
self._min_value: int = 0
self._max_value: int = 100
self._value: int = 0
self._wrap_selector_wheel = True
self._on_value_change: Optional[Callable] = None
self._on_scroll: Optional[Callable] = None
self._displayed_values: Optional[List[str]] = None
self._descendant_focus = False
def setMinValue(self, value: int) -> None:
self._min_value = value
if self._value < value:
self._value = value
def getMinValue(self) -> int:
return self._min_value
def setMaxValue(self, value: int) -> None:
self._max_value = value
if self._value > value:
self._value = value
def getMaxValue(self) -> int:
return self._max_value
def setValue(self, value: int) -> None:
self._value = max(self._min_value, min(self._max_value, value))
if self._on_value_change:
self._on_value_change(self, self._value, self._value)
def getValue(self) -> int:
return self._value
def setWrapSelectorWheel(self, wrap: bool) -> None:
self._wrap_selector_wheel = wrap
def getWrapSelectorWheel(self) -> bool:
return self._wrap_selector_wheel
def setDisplayedValues(self, values: Optional[List[str]]) -> None:
self._displayed_values = values
def getDisplayedValues(self) -> Optional[List[str]]:
return self._displayed_values
def setOnValueChangedListener(self, listener: Optional[Callable]) -> None:
self._on_value_change = listener
def setOnScrollListener(self, listener: Optional[Callable]) -> None:
self._on_scroll = listener
def toString(self) -> str:
return f"NumberPicker(value={self._value}, range=[{self._min_value}-{self._max_value}])"
class SearchView(Stub):
"""SearchView — 搜索视图扩展"""
ICONIFIED = 0
EXPANDED = 1
COLLAPSED = 2
def __init__(self, context: Any = None):
super().__init__()
self._query: str = ""
self._query_hint: Optional[str] = None
self._iconified = True
self._iconified_by_default = True
self._submit_button_enabled = True
self._query_refinement_enabled = False
self._searchable_info: Optional[Any] = None
self._on_query: Optional[Callable] = None
self._on_query_text: Optional[Callable] = None
self._on_close: Optional[Callable] = None
self._on_suggestion: Optional[Callable] = None
def setQuery(self, query: str, submit: bool = False) -> None:
self._query = query
if submit and self._on_query:
self._on_query(query)
def getQuery(self) -> str:
return self._query
def setQueryHint(self, hint: Optional[str]) -> None:
self._query_hint = hint
def getQueryHint(self) -> Optional[str]:
return self._query_hint
def setIconified(self, iconified: bool) -> None:
self._iconified = iconified
def isIconified(self) -> bool:
return self._iconified
def setIconifiedByDefault(self, iconified: bool) -> None:
self._iconified_by_default = iconified
def isIconifiedByDefault(self) -> bool:
return self._iconified_by_default
def setSubmitButtonEnabled(self, enabled: bool) -> None:
self._submit_button_enabled = enabled
def isSubmitButtonEnabled(self) -> bool:
return self._submit_button_enabled
def setQueryRefinementEnabled(self, enabled: bool) -> None:
self._query_refinement_enabled = enabled
def isQueryRefinementEnabled(self) -> bool:
return self._query_refinement_enabled
def setOnQueryTextListener(self, listener: Optional[Callable]) -> None:
self._on_query_text = listener
def setOnCloseListener(self, listener: Optional[Callable]) -> None:
self._on_close = listener
def setOnSuggestionListener(self, listener: Optional[Callable]) -> None:
self._on_suggestion = listener
def setSearchableInfo(self, info: Any) -> None:
self._searchable_info = info
def onActionViewExpanded(self) -> None:
self._iconified = False
def onActionViewCollapsed(self) -> None:
self._iconified = True
def toString(self) -> str:
return f"SearchView(query={self._query})"
class TabHost(Stub):
"""TabHost — 标签宿主"""
class TabSpec(Stub):
"""TabHost.TabSpec — 标签规格"""
def __init__(self, tag: str = ""):
super().__init__()
self._tag = tag
self._indicator: Optional[Any] = None
self._content: Optional[Any] = None
def setIndicator(self, indicator: Any) -> "TabHost.TabSpec":
self._indicator = indicator
return self
def setContent(self, content: Any) -> "TabHost.TabSpec":
self._content = content
return self
def getTag(self) -> str:
return self._tag
def toString(self) -> str:
return f"TabSpec(tag={self._tag})"
def __init__(self, context: Any = None):
super().__init__()
self._tabs: List[TabHost.TabSpec] = []
self._current_tab: int = 0
def newTabSpec(self, tag: str) -> TabSpec:
return TabHost.TabSpec(tag)
def addTab(self, spec: TabSpec) -> None:
self._tabs.append(spec)
def setCurrentTab(self, index: int) -> None:
if 0 <= index < len(self._tabs):
self._current_tab = index
def setCurrentTabByTag(self, tag: str) -> None:
for i, spec in enumerate(self._tabs):
if spec.getTag() == tag:
self._current_tab = i
break
def getCurrentTab(self) -> int:
return self._current_tab
def getCurrentTabTag(self) -> str:
if 0 <= self._current_tab < len(self._tabs):
return self._tabs[self._current_tab].getTag()
return ""
def getTabWidget(self) -> Optional["TabWidget"]:
return None
def getTabContentView(self) -> Optional[Any]:
return None
def getTabCount(self) -> int:
return len(self._tabs)
def toString(self) -> str:
return f"TabHost(tabs={len(self._tabs)}, current={self._current_tab})"
class TabWidget(Stub):
"""TabWidget — 标签小部件"""
def __init__(self, context: Any = None):
super().__init__()
self._tabs: List[Any] = []
self._current_tab: int = 0
self._strip_enabled = False
self._strip_left: int = 0
self._strip_top: int = 0
self._strip_right: int = 0
self._strip_bottom: int = 0
def setCurrentTab(self, index: int) -> None:
self._current_tab = max(0, min(index, len(self._tabs) - 1))
def getCurrentTab(self) -> int:
return self._current_tab
def setStripEnabled(self, enabled: bool) -> None:
self._strip_enabled = enabled
def isStripEnabled(self) -> bool:
return self._strip_enabled
def getTabCount(self) -> int:
return len(self._tabs)
def toString(self) -> str:
return f"TabWidget(tabs={len(self._tabs)})"
# ═══════════════════════════════════════════════════════════════
# TextSwitcher / ViewSwitcher / ViewAnimator / ImageSwitcher
# ═══════════════════════════════════════════════════════════════
class ViewAnimator(Stub):
"""ViewAnimator — 视图动画器"""
def __init__(self, context: Any = None):
super().__init__()
self._children: List[Any] = []
self._displayed_child: int = 0
self._in_animation: Optional[Any] = None
self._out_animation: Optional[Any] = None
self._animate_first_view = False
def addView(self, child: Any) -> None:
self._children.append(child)
def removeView(self, child: Any) -> None:
if child in self._children:
self._children.remove(child)
def removeAllViews(self) -> None:
self._children.clear()
def getChildCount(self) -> int:
return len(self._children)
def getCurrentView(self) -> Optional[Any]:
if 0 <= self._displayed_child < len(self._children):
return self._children[self._displayed_child]
return None
def getDisplayedChild(self) -> int:
return self._displayed_child
def setDisplayedChild(self, index: int) -> None:
if 0 <= index < len(self._children):
self._displayed_child = index
def showNext(self) -> None:
if self._children:
self._displayed_child = (self._displayed_child + 1) % len(self._children)
def showPrevious(self) -> None:
if self._children:
self._displayed_child = (self._displayed_child - 1) % len(self._children)
def setInAnimation(self, animation: Any) -> None:
self._in_animation = animation
def getInAnimation(self) -> Optional[Any]:
return self._in_animation
def setOutAnimation(self, animation: Any) -> None:
self._out_animation = animation
def getOutAnimation(self) -> Optional[Any]:
return self._out_animation
def setAnimateFirstView(self, animate: bool) -> None:
self._animate_first_view = animate
def getAnimateFirstView(self) -> bool:
return self._animate_first_view
def toString(self) -> str:
return f"ViewAnimator(children={len(self._children)}, displayed={self._displayed_child})"
class ViewSwitcher(ViewAnimator):
"""ViewSwitcher — 视图切换器"""
class ViewFactory(Stub):
"""ViewSwitcher.ViewFactory — 视图工厂"""
def makeView(self) -> Any:
return None
def __init__(self, context: Any = None):
super().__init__(context)
self._factory: Optional[ViewSwitcher.ViewFactory] = None
def setFactory(self, factory: ViewFactory) -> None:
self._factory = factory
def getNextView(self) -> Optional[Any]:
next_idx = (self.getDisplayedChild() + 1) % max(1, self.getChildCount())
if 0 <= next_idx < self.getChildCount():
return None
return None
def reset(self) -> None:
self.removeAllViews()
def toString(self) -> str:
return f"ViewSwitcher()"
class TextSwitcher(ViewSwitcher):
"""TextSwitcher — 文本切换器"""
def __init__(self, context: Any = None):
super().__init__(context)
self._factory = None
def setCurrentText(self, text: str) -> None:
pass
def getCurrentText(self) -> str:
return ""
def toString(self) -> str:
return "TextSwitcher()"
class ImageSwitcher(ViewSwitcher):
"""ImageSwitcher — 图片切换器"""
def __init__(self, context: Any = None):
super().__init__(context)
def setImageResource(self, res_id: int) -> None:
pass
def setImageDrawable(self, drawable: Any) -> None:
pass
def setImageURI(self, uri: Any) -> None:
pass
def toString(self) -> str:
return "ImageSwitcher()"
class ImageButton(Stub):
"""ImageButton — 图片按钮"""
def __init__(self, context: Any = None):
super().__init__()
self._adjust_view_bounds = False
self._scale_type: Optional[Any] = None
def setAdjustViewBounds(self, adjust: bool) -> None:
self._adjust_view_bounds = adjust
def getAdjustViewBounds(self) -> bool:
return self._adjust_view_bounds
def setScaleType(self, scale_type: Any) -> None:
self._scale_type = scale_type
def getScaleType(self) -> Optional[Any]:
return self._scale_type
def toString(self) -> str:
return "ImageButton()"
class ZoomButton(ImageButton):
"""ZoomButton — 缩放按钮"""
def __init__(self, context: Any = None):
super().__init__(context)
self._zoom_in = False
self._zoom_speed: int = 300
self._on_click: Optional[Callable] = None
def setZoomIn(self, zoom_in: bool) -> None:
self._zoom_in = zoom_in
def isZoomIn(self) -> bool:
return self._zoom_in
def setZoomSpeed(self, speed: int) -> None:
self._zoom_speed = speed
def getZoomSpeed(self) -> int:
return self._zoom_speed
def setOnZoomListener(self, listener: Optional[Callable]) -> None:
self._on_click = listener
def toString(self) -> str:
return f"ZoomButton(zoomIn={self._zoom_in})"
class ZoomControls(Stub):
"""ZoomControls — 缩放控件"""
def __init__(self, context: Any = None):
super().__init__()
self._zoom_in_enabled = True
self._zoom_out_enabled = True
self._on_zoom_in: Optional[Callable] = None
self._on_zoom_out: Optional[Callable] = None
self._show_zoom_controls = True
def setOnZoomInClickListener(self, listener: Optional[Callable]) -> None:
self._on_zoom_in = listener
def setOnZoomOutClickListener(self, listener: Optional[Callable]) -> None:
self._on_zoom_out = listener
def setZoomInEnabled(self, enabled: bool) -> None:
self._zoom_in_enabled = enabled
def setZoomOutEnabled(self, enabled: bool) -> None:
self._zoom_out_enabled = enabled
def show(self) -> None:
self._show_zoom_controls = True
def hide(self) -> None:
self._show_zoom_controls = False
def setIsZoomInEnabled(self, enabled: bool) -> None:
self._zoom_in_enabled = enabled
def setIsZoomOutEnabled(self, enabled: bool) -> None:
self._zoom_out_enabled = enabled
def hasFocus(self) -> bool:
return False
def toString(self) -> str:
return "ZoomControls()"
# ═══════════════════════════════════════════════════════════════
# DigitalClock / TextClock / AnalogClock
# ═══════════════════════════════════════════════════════════════
class DigitalClock(Stub):
"""DigitalClock — 数字时钟"""
def __init__(self, context: Any = None):
super().__init__()
self._format: str = "%H:%M:%S"
self._on_tick: Optional[Callable] = None
def setFormat(self, format_str: str) -> None:
self._format = format_str
def getFormat(self) -> str:
return self._format
def getTime(self) -> str:
import datetime
return datetime.datetime.now().strftime(self._format)
def setOnTickListener(self, listener: Optional[Callable]) -> None:
self._on_tick = listener
def toString(self) -> str:
return f"DigitalClock(time={self.getTime()})"
class TextClock(Stub):
"""TextClock — 文本时钟"""
def __init__(self, context: Any = None):
super().__init__()
self._format_12_hour: str = "hh:mm:ss a"
self._format_24_hour: str = "HH:mm:ss"
self._time_zone: Optional[str] = None
def setFormat12Hour(self, format_str: str) -> None:
self._format_12_hour = format_str
def getFormat12Hour(self) -> str:
return self._format_12_hour
def setFormat24Hour(self, format_str: str) -> None:
self._format_24_hour = format_str
def getFormat24Hour(self) -> str:
return self._format_24_hour
def setTimeZone(self, tz: str) -> None:
self._time_zone = tz
def getTimeZone(self) -> Optional[str]:
return self._time_zone
def is24HourModeEnabled(self) -> bool:
return True
def getText(self) -> str:
import datetime
if self._time_zone:
import pytz
now = datetime.datetime.now(pytz.timezone(self._time_zone))
else:
now = datetime.datetime.now()
return now.strftime(self._format_24_hour)
def toString(self) -> str:
return f"TextClock(time={self.getText()})"
class AnalogClock(Stub):
"""AnalogClock — 模拟时钟"""
def __init__(self, context: Any = None):
super().__init__()
self._dial: Optional[Any] = None
self._hour_hand: Optional[Any] = None
self._minute_hand: Optional[Any] = None
self._second_hand: Optional[Any] = None
def toString(self) -> str:
return "AnalogClock()"
# ═══════════════════════════════════════════════════════════════
# QuickContactBadge
# ═══════════════════════════════════════════════════════════════
class QuickContactBadge(Stub):
"""QuickContactBadge — 快速联系人徽章"""
MODE_SMALL = 0
MODE_MEDIUM = 1
MODE_LARGE = 2
def __init__(self, context: Any = None):
super().__init__()
self._contact_uri: Optional[str] = None
self._mode = self.MODE_MEDIUM
self._on_click: Optional[Callable] = None
def assignContactUri(self, uri: str) -> None:
self._contact_uri = uri
def assignContactFromEmail(self, email: str, lazy: bool = False) -> None:
self._contact_uri = f"mailto:{email}"
def assignContactFromPhone(self, phone: str, lazy: bool = False) -> None:
self._contact_uri = f"tel:{phone}"
def setMode(self, mode: int) -> None:
self._mode = mode
def getMode(self) -> int:
return self._mode
def setOnClickListener(self, listener: Optional[Callable]) -> None:
self._on_click = listener
def toString(self) -> str:
return f"QuickContactBadge(contact={self._contact_uri})"
# ═══════════════════════════════════════════════════════════════
# 各种 Adapter 实现
# ═══════════════════════════════════════════════════════════════
class BaseAdapter(Adapter):
"""BaseAdapter — 基础适配器"""
def __init__(self):
super().__init__()
self._data_set_observers: List[Callable] = []
def registerDataSetObserver(self, observer: Callable) -> None:
if observer not in self._data_set_observers:
self._data_set_observers.append(observer)
def unregisterDataSetObserver(self, observer: Callable) -> None:
if observer in self._data_set_observers:
self._data_set_observers.remove(observer)
def notifyDataSetChanged(self) -> None:
for obs in list(self._data_set_observers):
obs()
def notifyDataSetInvalidated(self) -> None:
self.notifyDataSetChanged()
def areAllItemsEnabled(self) -> bool:
return True
def isEnabled(self, position: int) -> bool:
return True
def getItemViewType(self, position: int) -> int:
return Adapter.IGNORE_ITEM_VIEW_TYPE
def getViewTypeCount(self) -> int:
return 1
def hasStableIds(self) -> bool:
return False
def isEmpty(self) -> bool:
return self.getCount() == 0
class ArrayAdapter(BaseAdapter):
"""ArrayAdapter — 数组适配器"""
def __init__(self, context: Any = None, resource: int = 0,
objects: Optional[List[Any]] = None):
super().__init__()
self._context = context
self._resource = resource
self._drop_down_resource: int = resource
self._objects: List[Any] = list(objects) if objects else []
self._lock = threading.Lock()
def add(self, obj: Any) -> None:
with self._lock:
self._objects.append(obj)
self.notifyDataSetChanged()
def addAll(self, collection: List[Any]) -> None:
with self._lock:
self._objects.extend(collection)
self.notifyDataSetChanged()
def insert(self, obj: Any, index: int) -> None:
with self._lock:
self._objects.insert(index, obj)
self.notifyDataSetChanged()
def remove(self, obj: Any) -> None:
with self._lock:
if obj in self._objects:
self._objects.remove(obj)
self.notifyDataSetChanged()
def clear(self) -> None:
with self._lock:
self._objects.clear()
self.notifyDataSetChanged()
def sort(self, comparator: Callable) -> None:
with self._lock:
self._objects.sort(key=comparator)
self.notifyDataSetChanged()
def getCount(self) -> int:
return len(self._objects)
def getItem(self, position: int) -> Optional[Any]:
if 0 <= position < len(self._objects):
return self._objects[position]
return None
def getPosition(self, item: Any) -> int:
try:
return self._objects.index(item)
except ValueError:
return -1
def setDropDownViewResource(self, resource: int) -> None:
self._drop_down_resource = resource
def getDropDownViewResource(self) -> int:
return self._drop_down_resource
def toString(self) -> str:
return f"ArrayAdapter(items={len(self._objects)})"
class SimpleAdapter(BaseAdapter):
"""SimpleAdapter — 简单适配器"""
def __init__(self, context: Any = None,
data: Optional[List[Dict[str, Any]]] = None,
resource: int = 0,
from_keys: Optional[List[str]] = None,
to_ids: Optional[List[int]] = None):
super().__init__()
self._context = context
self._data: List[Dict[str, Any]] = data or []
self._resource = resource
self._from_keys: List[str] = list(from_keys) if from_keys else []
self._to_ids: List[int] = list(to_ids) if to_ids else []
self._drop_down_resource: int = resource
self._view_binder: Optional[Callable] = None
def getCount(self) -> int:
return len(self._data)
def getItem(self, position: int) -> Optional[Dict[str, Any]]:
if 0 <= position < len(self._data):
return self._data[position]
return None
def getViewBinder(self) -> Optional[Callable]:
return self._view_binder
def setViewBinder(self, binder: Optional[Callable]) -> None:
self._view_binder = binder
def setDropDownViewResource(self, resource: int) -> None:
self._drop_down_resource = resource
def getDropDownViewResource(self) -> int:
return self._drop_down_resource
def toString(self) -> str:
return f"SimpleAdapter(items={len(self._data)})"
class CursorAdapter(BaseAdapter):
"""CursorAdapter — 游标适配器"""
FLAG_AUTO_REQUERY = 1
FLAG_REGISTER_CONTENT_OBSERVER = 2
def __init__(self, context: Any = None, cursor: Any = None,
flags: int = FLAG_AUTO_REQUERY):
super().__init__()
self._context = context
self._cursor = cursor
self._flags = flags
self._row_id_column: str = "_id"
self._lock = threading.Lock()
def getCursor(self) -> Optional[Any]:
return self._cursor
def setCursor(self, cursor: Any) -> None:
self._cursor = cursor
self.notifyDataSetChanged()
def getCount(self) -> int:
return 0
def getItem(self, position: int) -> Optional[Any]:
return None
def getItemId(self, position: int) -> int:
return position
def changeCursor(self, cursor: Any) -> Optional[Any]:
old = self._cursor
self._cursor = cursor
self.notifyDataSetChanged()
return old
def swapCursor(self, cursor: Any) -> Optional[Any]:
old = self._cursor
self._cursor = cursor
self.notifyDataSetChanged()
return old
def toString(self) -> str:
return f"CursorAdapter(cursor={'yes' if self._cursor else 'no'})"
class ResourceCursorAdapter(CursorAdapter):
"""ResourceCursorAdapter — 资源游标适配器"""
def __init__(self, context: Any = None, layout: int = 0,
cursor: Any = None, flags: int = CursorAdapter.FLAG_AUTO_REQUERY):
super().__init__(context, cursor, flags)
self._layout = layout
self._drop_down_layout: int = layout
def setDropDownViewResource(self, resource: int) -> None:
self._drop_down_layout = resource
def getDropDownViewResource(self) -> int:
return self._drop_down_layout
def toString(self) -> str:
return "ResourceCursorAdapter()"
class SimpleCursorAdapter(ResourceCursorAdapter):
"""SimpleCursorAdapter — 简单游标适配器"""
def __init__(self, context: Any = None, layout: int = 0,
cursor: Any = None, from_columns: Optional[List[str]] = None,
to_views: Optional[List[int]] = None,
flags: int = CursorAdapter.FLAG_AUTO_REQUERY):
super().__init__(context, layout, cursor, flags)
self._from_columns: List[str] = list(from_columns) if from_columns else []
self._to_views: List[int] = list(to_views) if to_views else []
self._view_binder: Optional[Callable] = None
self._cursor_to_column_map: Optional[Dict[str, int]] = None
def getViewBinder(self) -> Optional[Callable]:
return self._view_binder
def setViewBinder(self, binder: Optional[Callable]) -> None:
self._view_binder = binder
def setCursorToStringConverter(self, converter: Optional[Callable]) -> None:
pass
def toString(self) -> str:
return "SimpleCursorAdapter()"
class HeaderViewListAdapter(Stub):
"""HeaderViewListAdapter — 头部视图列表适配器包装"""
def __init__(self, wrapped_adapter: Optional[Adapter] = None):
super().__init__()
self._wrapped: Optional[Adapter] = wrapped_adapter
self._headers: List[Any] = []
self._footers: List[Any] = []
def addHeaderView(self, view: Any, data: Any = None, is_selectable: bool = True) -> None:
self._headers.append(view)
def addFooterView(self, view: Any, data: Any = None, is_selectable: bool = True) -> None:
self._footers.append(view)
def removeHeaderView(self, view: Any) -> bool:
if view in self._headers:
self._headers.remove(view)
return True
return False
def removeFooterView(self, view: Any) -> bool:
if view in self._footers:
self._footers.remove(view)
return True
return False
def getCount(self) -> int:
base = self._wrapped.getCount() if self._wrapped else 0
return base + len(self._headers) + len(self._footers)
def getWrappedAdapter(self) -> Optional[Adapter]:
return self._wrapped
def getHeadersCount(self) -> int:
return len(self._headers)
def getFootersCount(self) -> int:
return len(self._footers)
def isEmpty(self) -> bool:
return self.getCount() == 0
def toString(self) -> str:
return (f"HeaderViewListAdapter(headers={len(self._headers)}, "
f"footers={len(self._footers)})")
class WrapperListAdapter(Adapter):
"""WrapperListAdapter — 包装列表适配器"""
def __init__(self, wrapped: Optional[Adapter] = None):
super().__init__()
self._wrapped = wrapped
def getWrappedAdapter(self) -> Optional[Adapter]:
return self._wrapped
def getCount(self) -> int:
return self._wrapped.getCount() if self._wrapped else 0
def getItem(self, position: int) -> Optional[Any]:
return self._wrapped.getItem(position) if self._wrapped else None
def getItemId(self, position: int) -> int:
return self._wrapped.getItemId(position) if self._wrapped else position
def getView(self, position: int, convert_view: Optional[Any],
parent: Any) -> Optional[Any]:
return self._wrapped.getView(position, convert_view, parent) if self._wrapped else None
def toString(self) -> str:
return "WrapperListAdapter()"