""" 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 .widget import AdapterView as _BaseAdapterView from .widget import AutoCompleteTextView as _BaseAutoCompleteTextView from .widget import ProgressBar as _BaseProgressBar from .widget import Chronometer as _BaseChronometer from .widget import TableLayout as _BaseTableLayout from .widget import TableRow as _BaseTableRow from .widget import LinearLayout as _BaseLinearLayout from .widget import FrameLayout as _BaseFrameLayout from .widget import RelativeLayout as _BaseRelativeLayout from .widget import NumberPicker as _BaseNumberPicker from .widget import SearchView as _BaseSearchView from .widget import TabHost as _BaseTabHost from .widget import TabWidget as _BaseTabWidget from .widget import ViewAnimator as _BaseViewAnimator from .widget import ImageButton as _BaseImageButton from .widget import ZoomControls as _BaseZoomControls from .widget import DigitalClock as _BaseDigitalClock from .widget import AnalogClock as _BaseAnalogClock from .widget import ToggleButton as _BaseToggleButton from .widget import RadioButton as _BaseRadioButton from .widget import SeekBar as _BaseSeekBar from .widget import RatingBar as _BaseRatingBar from .widget import ViewSwitcher as _BaseViewSwitcher from .widget import TextSwitcher as _BaseTextSwitcher from .widget import ImageSwitcher as _BaseImageSwitcher from .widget import BaseAdapter as _BaseBaseAdapter from .widget import ArrayAdapter as _BaseArrayAdapter from .widget import SimpleAdapter as _BaseSimpleAdapter from .widget import CursorAdapter as _BaseCursorAdapter 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(_BaseAdapterView): """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(_BaseAutoCompleteTextView): """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(_BaseProgressBar): """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(_BaseSeekBar, AbsSeekBar): """SeekBar — 拖动条""" def __init__(self, context: Any = None): AbsSeekBar.__init__(self, 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(_BaseRatingBar, ProgressBar): """RatingBar — 评分条""" def __init__(self, context: Any = None, num_stars: int = 5, step_size: float = 0.5): ProgressBar.__init__(self, 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(_BaseChronometer): """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(_BaseToggleButton, CompoundButton): """ToggleButton — 开关按钮""" def __init__(self, context: Any = None): super().__init__(context) CompoundButton.__init__(self, 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(_BaseRadioButton, CompoundButton): """RadioButton — 单选按钮""" def __init__(self, context: Any = None): super().__init__(context) CompoundButton.__init__(self, 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(_BaseTableLayout): """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(_BaseTableRow): """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(_BaseLinearLayout): """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(_BaseFrameLayout): """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(_BaseRelativeLayout): """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(_BaseNumberPicker): """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(_BaseSearchView): """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(_BaseTabHost): """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(_BaseTabWidget): """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(_BaseViewAnimator): """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(_BaseViewSwitcher, ViewAnimator): """ViewSwitcher — 视图切换器""" class ViewFactory(Stub): """ViewSwitcher.ViewFactory — 视图工厂""" def makeView(self) -> Any: return None def __init__(self, context: Any = None): super().__init__(context) ViewAnimator.__init__(self, 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(_BaseTextSwitcher, ViewSwitcher): """TextSwitcher — 文本切换器""" def __init__(self, context: Any = None): super().__init__(context) ViewSwitcher.__init__(self, context) self._factory = None def setCurrentText(self, text: str) -> None: pass def getCurrentText(self) -> str: return "" def toString(self) -> str: return "TextSwitcher()" class ImageSwitcher(_BaseImageSwitcher, ViewSwitcher): """ImageSwitcher — 图片切换器""" def __init__(self, context: Any = None): super().__init__(context) ViewSwitcher.__init__(self, 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(_BaseImageButton): """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(_BaseZoomControls): """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(_BaseDigitalClock): """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(_BaseAnalogClock): """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(_BaseBaseAdapter, 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(_BaseArrayAdapter, BaseAdapter): """ArrayAdapter — 数组适配器""" def __init__(self, context: Any = None, resource: int = 0, objects: Optional[List[Any]] = None): BaseAdapter.__init__(self) 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(_BaseSimpleAdapter, 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): BaseAdapter.__init__(self) 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(_BaseCursorAdapter, 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): BaseAdapter.__init__(self) 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()"