""" Android Widget Adapter 组件 — ListAdapter, SpinnerAdapter, ArrayAdapter (扩展), CursorAdapter (扩展), RecyclerView.Adapter (扩展), RecyclerView.ViewHolder, PagerAdapter, FragmentPagerAdapter, PagerTitleStrip 等 方法签名完全对齐 Android SDK """ from __future__ import annotations from typing import Any, Callable, Dict, Generic, List, Optional, Tuple, TypeVar from .._core import Stub, AndroidOnlyError T = TypeVar("T") __all__ = [ "ListAdapter", "SpinnerAdapter", "WrapperListAdapter", "HeaderViewListAdapter", "ArrayAdapter", "CursorAdapter", "SimpleCursorAdapter", "ResourceCursorAdapter", "SimpleAdapter", "BaseAdapter", "RecyclerView", "PagerAdapter", "FragmentPagerAdapter", "FragmentStatePagerAdapter", "PagerTitleStrip", "PagerTabStrip", ] # ═══════════════════════════════════════════════════════════════ # 适配器常量 # ═══════════════════════════════════════════════════════════════ ADAPTER_IGNORE_ITEM_VIEW_TYPE = -1 ADAPTER_NO_SELECTION = -1 ADAPTER_INVALID_POSITION = -1 ADAPTER_INVALID_ROW_ID = -1 ADAPTER_HAS_STABLE_IDS = True ADAPTER_NO_STABLE_IDS = False PAGER_POSITION_UNCHANGED = -1 PAGER_POSITION_NONE = -2 # ═══════════════════════════════════════════════════════════════ # BaseAdapter (扩展) # ═══════════════════════════════════════════════════════════════ class BaseAdapter(Stub): """BaseAdapter — 基础适配器 (完整版)""" def __init__(self): super().__init__() self._observers: List[Any] = [] def getCount(self) -> int: return 0 def getItem(self, position: int) -> Optional[Any]: return None def getItemId(self, position: int) -> int: return position def getView(self, position: int, convertView: Any, parent: Any) -> Any: return None 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 registerDataSetObserver(self, observer: Any): self._observers.append(observer) def unregisterDataSetObserver(self, observer: Any): self._observers = [o for o in self._observers if o is not observer] def notifyDataSetChanged(self): for o in self._observers: if hasattr(o, 'onChanged'): o.onChanged() def notifyDataSetInvalidated(self): for o in self._observers: if hasattr(o, 'onInvalidated'): o.onInvalidated() def areAllItemsEnabled(self) -> bool: return True def isEnabled(self, position: int) -> bool: return True def getDropDownView(self, position: int, convertView: Any, parent: Any) -> Any: return self.getView(position, convertView, parent) def toString(self) -> str: return f"BaseAdapter(count={self.getCount()})" def equals(self, other: Any) -> bool: return self is other def hashCode(self) -> int: return id(self) & 0x7FFFFFFF # ═══════════════════════════════════════════════════════════════ # ListAdapter # ═══════════════════════════════════════════════════════════════ class ListAdapter(Stub): """ListAdapter — 列表适配器接口""" def getCount(self) -> int: return 0 def getItem(self, position: int) -> Optional[Any]: return None def getItemId(self, position: int) -> int: return position def getView(self, position: int, convertView: Any, parent: Any) -> Any: return None def isEmpty(self) -> bool: return self.getCount() == 0 def registerDataSetObserver(self, observer: Any): pass def unregisterDataSetObserver(self, observer: Any): pass 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 toString(self) -> str: return f"ListAdapter@{hex(id(self))}" # ═══════════════════════════════════════════════════════════════ # SpinnerAdapter # ═══════════════════════════════════════════════════════════════ class SpinnerAdapter(Stub): """SpinnerAdapter — 下拉适配器接口""" def getCount(self) -> int: return 0 def getItem(self, position: int) -> Optional[Any]: return None def getItemId(self, position: int) -> int: return position def getView(self, position: int, convertView: Any, parent: Any) -> Any: return None def getDropDownView(self, position: int, convertView: Any, parent: Any) -> Any: return self.getView(position, convertView, parent) def toString(self) -> str: return f"SpinnerAdapter@{hex(id(self))}" # ═══════════════════════════════════════════════════════════════ # WrapperListAdapter # ═══════════════════════════════════════════════════════════════ class WrapperListAdapter(Stub): """WrapperListAdapter — 包装列表适配器""" def getWrappedAdapter(self) -> Optional[ListAdapter]: return None def getCount(self) -> int: wrapped = self.getWrappedAdapter() return wrapped.getCount() if wrapped else 0 def getItem(self, position: int) -> Optional[Any]: wrapped = self.getWrappedAdapter() return wrapped.getItem(position) if wrapped else None def getItemId(self, position: int) -> int: wrapped = self.getWrappedAdapter() return wrapped.getItemId(position) if wrapped else position def toString(self) -> str: return f"WrapperListAdapter@{hex(id(self))}" # ═══════════════════════════════════════════════════════════════ # HeaderViewListAdapter # ═══════════════════════════════════════════════════════════════ class HeaderViewListAdapter(WrapperListAdapter): """HeaderViewListAdapter — 页眉视图列表适配器""" def __init__(self, wrappedAdapter: Optional[ListAdapter] = None): super().__init__() self._wrapped_adapter = wrappedAdapter self._headers: List[Any] = [] self._footers: List[Any] = [] def getWrappedAdapter(self) -> Optional[ListAdapter]: return self._wrapped_adapter def addHeader(self, view: Any, data: Any = None, isSelectable: bool = True): self._headers.append((view, data, isSelectable)) def addFooter(self, view: Any, data: Any = None, isSelectable: bool = True): self._footers.append((view, data, isSelectable)) def removeHeader(self, view: Any) -> bool: for i, (v, _, _) in enumerate(self._headers): if v is view: self._headers.pop(i) return True return False def removeFooter(self, view: Any) -> bool: for i, (v, _, _) in enumerate(self._footers): if v is view: self._footers.pop(i) return True return False def getHeadersCount(self) -> int: return len(self._headers) def getFootersCount(self) -> int: return len(self._footers) def getCount(self) -> int: count = len(self._headers) + len(self._footers) if self._wrapped_adapter: count += self._wrapped_adapter.getCount() return count def getItem(self, position: int) -> Optional[Any]: if position < len(self._headers): return self._headers[position][1] offset = position - len(self._headers) if self._wrapped_adapter and offset < self._wrapped_adapter.getCount(): return self._wrapped_adapter.getItem(offset) footer_offset = offset - (self._wrapped_adapter.getCount() if self._wrapped_adapter else 0) if 0 <= footer_offset < len(self._footers): return self._footers[footer_offset][1] return None def getView(self, position: int, convertView: Any, parent: Any) -> Any: if position < len(self._headers): return self._headers[position][0] offset = position - len(self._headers) if self._wrapped_adapter and offset < self._wrapped_adapter.getCount(): return self._wrapped_adapter.getView(offset, convertView, parent) footer_offset = offset - (self._wrapped_adapter.getCount() if self._wrapped_adapter else 0) if 0 <= footer_offset < len(self._footers): return self._footers[footer_offset][0] return None def toString(self) -> str: return f"HeaderViewListAdapter(headers={len(self._headers)}, footers={len(self._footers)})" # ═══════════════════════════════════════════════════════════════ # ArrayAdapter (扩展) # ═══════════════════════════════════════════════════════════════ class ArrayAdapter(BaseAdapter): """ArrayAdapter — 数组适配器 (完整版)""" def __init__(self, context: Any = None, resource: int = 0, textViewResourceId: int = 0, objects: List[Any] = None): super().__init__() self._context = context self._resource = resource self._text_view_resource_id = textViewResourceId self._objects: List[Any] = list(objects) if objects else [] self._drop_down_resource = resource self._field_id = 0 self._filter: Optional[Any] = None def add(self, obj: Any): self._objects.append(obj) self.notifyDataSetChanged() def addAll(self, *objects: Any): for obj in objects: self._objects.append(obj) self.notifyDataSetChanged() def insert(self, obj: Any, index: int): self._objects.insert(index, obj) self.notifyDataSetChanged() def remove(self, obj: Any): if obj in self._objects: self._objects.remove(obj) self.notifyDataSetChanged() def clear(self): self._objects.clear() self.notifyDataSetChanged() def sort(self, comparator: Callable[[Any, Any], int]): self._objects.sort(key=lambda x: x) 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 ADAPTER_INVALID_POSITION def setDropDownViewResource(self, resource: int): self._drop_down_resource = resource def getDropDownViewResource(self) -> int: return self._drop_down_resource def getContext(self) -> Any: return self._context def getFilter(self) -> Optional[Any]: return self._filter def createFromResource(context: Any, textArrayResId: int, textViewResId: int) -> "ArrayAdapter": return ArrayAdapter(context=context, resource=textViewResId) def toString(self) -> str: return f"ArrayAdapter(count={len(self._objects)})" # ═══════════════════════════════════════════════════════════════ # CursorAdapter (扩展) # ═══════════════════════════════════════════════════════════════ class CursorAdapter(BaseAdapter): """CursorAdapter — 游标适配器 (完整版)""" FLAG_AUTO_REQUERY = 0x01 FLAG_REGISTER_CONTENT_OBSERVER = 0x02 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 = "_id" self._count = 0 if cursor: self._count = len(cursor) if hasattr(cursor, '__len__') else 0 def getCursor(self) -> Any: return self._cursor def setCursor(self, cursor: Any): self._cursor = cursor self._count = len(cursor) if cursor and hasattr(cursor, '__len__') else 0 self.notifyDataSetChanged() def getCount(self) -> int: return self._count def getItem(self, position: int) -> Optional[Any]: if self._cursor and 0 <= position < self._count: if hasattr(self._cursor, '__getitem__'): return self._cursor[position] return self._cursor return None def getItemId(self, position: int) -> int: if self._cursor and 0 <= position < self._count: item = self.getItem(position) if item and hasattr(item, 'get'): return int(item.get(self._row_id_column, position)) return position def getView(self, position: int, convertView: Any, parent: Any) -> Any: return self.newView(self._context, self._cursor, parent) if not convertView else convertView def newView(self, context: Any, cursor: Any, parent: Any) -> Any: return None def bindView(self, view: Any, context: Any, cursor: Any): pass def changeCursor(self, cursor: Any): self.setCursor(cursor) def getFilterQueryProvider(self) -> Optional[Any]: return None def setFilterQueryProvider(self, provider: Any): pass def runQueryOnBackgroundThread(self, constraint: str) -> Any: return self._cursor def toString(self) -> str: return f"CursorAdapter(count={self._count})" # ═══════════════════════════════════════════════════════════════ # SimpleCursorAdapter (扩展) # ═══════════════════════════════════════════════════════════════ class SimpleCursorAdapter(CursorAdapter): """SimpleCursorAdapter — 简单游标适配器 (完整版)""" def __init__(self, context: Any = None, layout: int = 0, cursor: Any = None, fromColumns: List[str] = None, toViews: List[int] = None, flags: int = 0): super().__init__(context=context, cursor=cursor, flags=flags) self._layout = layout self._from_columns = fromColumns or [] self._to_views = toViews or [] def getLayout(self) -> int: return self._layout def setViewText(self, view: Any, text: str): pass def setViewImage(self, view: Any, value: str): pass def getStringConversionColumn(self) -> int: return 0 def setStringConversionColumn(self, column: int): pass def getViewBinder(self) -> Optional[Any]: return None def setViewBinder(self, viewBinder: Any): pass def toString(self) -> str: return f"SimpleCursorAdapter(layout={self._layout})" # ═══════════════════════════════════════════════════════════════ # ResourceCursorAdapter (扩展) # ═══════════════════════════════════════════════════════════════ class ResourceCursorAdapter(CursorAdapter): """ResourceCursorAdapter — 资源游标适配器 (完整版)""" def __init__(self, context: Any = None, layout: int = 0, cursor: Any = None, flags: int = 0, dropDownLayout: int = 0): super().__init__(context=context, cursor=cursor, flags=flags) self._layout = layout self._drop_down_layout = dropDownLayout or layout def setDropDownViewResource(self, dropDownLayout: int): self._drop_down_layout = dropDownLayout def getDropDownView(self, position: int, convertView: Any, parent: Any) -> Any: return self.newView(self._context, self._cursor, parent) def toString(self) -> str: return f"ResourceCursorAdapter(layout={self._layout})" # ═══════════════════════════════════════════════════════════════ # SimpleAdapter (扩展) # ═══════════════════════════════════════════════════════════════ class SimpleAdapter(BaseAdapter): """SimpleAdapter — 简单适配器 (完整版)""" def __init__(self, context: Any = None, data: List[Dict[str, Any]] = None, resource: int = 0, from_: List[str] = None, to: List[int] = None): super().__init__() self._context = context self._data = data or [] self._resource = resource self._from_keys = from_ or [] self._to_ids = to or [] self._drop_down_resource = resource 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 getItemId(self, position: int) -> int: return position def getView(self, position: int, convertView: Any, parent: Any) -> Any: return convertView def setDropDownViewResource(self, resource: int): self._drop_down_resource = resource def getDropDownView(self, position: int, convertView: Any, parent: Any) -> Any: return convertView def getContext(self) -> Any: return self._context def getData(self) -> List[Dict[str, Any]]: return list(self._data) def setData(self, data: List[Dict[str, Any]]): self._data = list(data) self.notifyDataSetChanged() def toString(self) -> str: return f"SimpleAdapter(count={len(self._data)})" # ═══════════════════════════════════════════════════════════════ # RecyclerView # ═══════════════════════════════════════════════════════════════ class RecyclerView(Stub): """RecyclerView — 循环视图""" HORIZONTAL = 0 VERTICAL = 1 NO_POSITION = -1 NO_ID = -1 INVALID_TYPE = -1 # ═══════════════════════════════════════════════════════════ # RecyclerView.Adapter (扩展) # ═══════════════════════════════════════════════════════════ class Adapter(BaseAdapter): """RecyclerView.Adapter — RecyclerView 适配器 (完整版)""" def __init__(self): super().__init__() self._has_stable_ids = False self._state_restoration_policy = 0 self._observers: List[RecyclerView.AdapterDataObserver] = [] def onCreateViewHolder(self, parent: Any, viewType: int) -> "RecyclerView.ViewHolder": raise NotImplementedError def onBindViewHolder(self, holder: "RecyclerView.ViewHolder", position: int): raise NotImplementedError def getItemCount(self) -> int: return 0 def getItemViewType(self, position: int) -> int: return ADAPTER_IGNORE_ITEM_VIEW_TYPE def setHasStableIds(self, hasStableIds: bool): self._has_stable_ids = hasStableIds def hasStableIds(self) -> bool: return self._has_stable_ids def onAttachedToRecyclerView(self, recyclerView: "RecyclerView"): pass def onDetachedFromRecyclerView(self, recyclerView: "RecyclerView"): pass def onViewAttachedToWindow(self, holder: "RecyclerView.ViewHolder"): pass def onViewDetachedFromWindow(self, holder: "RecyclerView.ViewHolder"): pass def onViewRecycled(self, holder: "RecyclerView.ViewHolder"): pass def onFailedToRecycleView(self, holder: "RecyclerView.ViewHolder") -> bool: return False def registerAdapterDataObserver(self, observer: "RecyclerView.AdapterDataObserver"): self._observers.append(observer) def unregisterAdapterDataObserver(self, observer: "RecyclerView.AdapterDataObserver"): self._observers = [o for o in self._observers if o is not observer] def notifyDataSetChanged(self): for o in self._observers: o.onChanged() def notifyItemChanged(self, position: int): for o in self._observers: o.onItemRangeChanged(position, 1) def notifyItemRangeChanged(self, positionStart: int, itemCount: int): for o in self._observers: o.onItemRangeChanged(positionStart, itemCount) def notifyItemInserted(self, position: int): for o in self._observers: o.onItemRangeInserted(position, 1) def notifyItemRangeInserted(self, positionStart: int, itemCount: int): for o in self._observers: o.onItemRangeInserted(positionStart, itemCount) def notifyItemRemoved(self, position: int): for o in self._observers: o.onItemRangeRemoved(position, 1) def notifyItemRangeRemoved(self, positionStart: int, itemCount: int): for o in self._observers: o.onItemRangeRemoved(positionStart, itemCount) def notifyItemMoved(self, fromPosition: int, toPosition: int): for o in self._observers: o.onItemRangeMoved(fromPosition, toPosition, 1) def getItemId(self, position: int) -> int: return position def toString(self) -> str: return f"RecyclerView.Adapter(items={self.getItemCount()})" # ═══════════════════════════════════════════════════════════ # RecyclerView.ViewHolder (扩展) # ═══════════════════════════════════════════════════════════ class ViewHolder(Stub): """RecyclerView.ViewHolder — 视图持有者 (完整版)""" def __init__(self, itemView: Any = None): super().__init__() self.itemView = itemView self._adapter_position = RecyclerView.NO_POSITION self._old_position = RecyclerView.NO_POSITION self._item_id = RecyclerView.NO_ID self._item_view_type = RecyclerView.INVALID_TYPE self._is_recyclable = True self._is_bound = False def getAdapterPosition(self) -> int: return self._adapter_position def getOldPosition(self) -> int: return self._old_position def getItemId(self) -> int: return self._item_id def getItemViewType(self) -> int: return self._item_view_type def setIsRecyclable(self, recyclable: bool): self._is_recyclable = recyclable def isRecyclable(self) -> bool: return self._is_recyclable def setIsBound(self, bound: bool): self._is_bound = bound def isBound(self) -> bool: return self._is_bound def toString(self) -> str: return f"ViewHolder(pos={self._adapter_position})" def equals(self, other: Any) -> bool: return self is other def hashCode(self) -> int: return id(self) & 0x7FFFFFFF # ═══════════════════════════════════════════════════════════ # RecyclerView.LayoutManager (扩展) # ═══════════════════════════════════════════════════════════ class LayoutManager(Stub): """RecyclerView.LayoutManager — 布局管理器 (完整版)""" def __init__(self): super().__init__() self._child_count = 0 self._item_count = 0 self._auto_measure = True def generateDefaultLayoutParams(self) -> Any: return None def onLayoutChildren(self, recycler: Any, state: Any): pass def getChildCount(self) -> int: return self._child_count def getItemCount(self) -> int: return self._item_count def setAutoMeasureEnabled(self, enabled: bool): self._auto_measure = enabled def isAutoMeasureEnabled(self) -> bool: return self._auto_measure def canScrollHorizontally(self) -> bool: return False def canScrollVertically(self) -> bool: return False def scrollToPosition(self, position: int): pass def smoothScrollToPosition(self, view: Any, state: Any, position: int): pass def computeVerticalScrollOffset(self, state: Any) -> int: return 0 def computeVerticalScrollExtent(self, state: Any) -> int: return 0 def computeVerticalScrollRange(self, state: Any) -> int: return 0 def computeHorizontalScrollOffset(self, state: Any) -> int: return 0 def computeHorizontalScrollExtent(self, state: Any) -> int: return 0 def computeHorizontalScrollRange(self, state: Any) -> int: return 0 def toString(self) -> str: return f"LayoutManager(children={self._child_count})" # ═══════════════════════════════════════════════════════════ # RecyclerView.AdapterDataObserver # ═══════════════════════════════════════════════════════════ class AdapterDataObserver(Stub): """RecyclerView.AdapterDataObserver — 适配器数据观察者""" def onChanged(self): pass def onItemRangeChanged(self, positionStart: int, itemCount: int): pass def onItemRangeInserted(self, positionStart: int, itemCount: int): pass def onItemRangeRemoved(self, positionStart: int, itemCount: int): pass def onItemRangeMoved(self, fromPosition: int, toPosition: int, itemCount: int): pass def toString(self) -> str: return f"AdapterDataObserver@{hex(id(self))}" # ═══════════════════════════════════════════════════════════ # RecyclerView.ItemDecoration # ═══════════════════════════════════════════════════════════ class ItemDecoration(Stub): """RecyclerView.ItemDecoration — 项目装饰""" def onDraw(self, canvas: Any, parent: "RecyclerView", state: Any): pass def onDrawOver(self, canvas: Any, parent: "RecyclerView", state: Any): pass def getItemOffsets(self, outRect: Any, view: Any, parent: "RecyclerView", state: Any): outRect.set(0, 0, 0, 0) def toString(self) -> str: return f"ItemDecoration@{hex(id(self))}" # ═══════════════════════════════════════════════════════════ # RecyclerView.ItemAnimator # ═══════════════════════════════════════════════════════════ class ItemAnimator(Stub): """RecyclerView.ItemAnimator — 项目动画器""" def animateDisappearance(self, holder: ViewHolder, preInfo: Any, postInfo: Any) -> bool: return False def animateAppearance(self, holder: ViewHolder, preInfo: Any, postInfo: Any) -> bool: return False def animatePersistence(self, holder: ViewHolder, preInfo: Any, postInfo: Any) -> bool: return False def animateChange(self, oldHolder: ViewHolder, newHolder: ViewHolder, preInfo: Any, postInfo: Any) -> bool: return False def endAnimation(self, holder: ViewHolder): pass def endAnimations(self): pass def isRunning(self) -> bool: return False def dispatchAnimationsFinished(self): pass def toString(self) -> str: return f"ItemAnimator@{hex(id(self))}" # ═══════════════════════════════════════════════════════════ # RecyclerView.SmoothScroller # ═══════════════════════════════════════════════════════════ class SmoothScroller(Stub): """RecyclerView.SmoothScroller — 平滑滚动器""" def start(self, recyclerView: "RecyclerView", layoutManager: LayoutManager, targetPosition: int): pass def stop(self): pass def isRunning(self) -> bool: return False def getTargetPosition(self) -> int: return RecyclerView.NO_POSITION def toString(self) -> str: return f"SmoothScroller@{hex(id(self))}" # ═══════════════════════════════════════════════════════════ # RecyclerView.OnScrollListener # ═══════════════════════════════════════════════════════════ class OnScrollListener(Stub): """RecyclerView.OnScrollListener — 滚动监听器""" SCROLL_STATE_IDLE = 0 SCROLL_STATE_DRAGGING = 1 SCROLL_STATE_SETTLING = 2 def onScrollStateChanged(self, recyclerView: "RecyclerView", newState: int): pass def onScrolled(self, recyclerView: "RecyclerView", dx: int, dy: int): pass def toString(self) -> str: return f"OnScrollListener@{hex(id(self))}" def __init__(self): super().__init__() self._adapter: Optional[RecyclerView.Adapter] = None self._layout_manager: Optional[RecyclerView.LayoutManager] = None self._item_animator: Optional[RecyclerView.ItemAnimator] = None self._scroll_listeners: List[RecyclerView.OnScrollListener] = [] self._item_decoration: Optional[RecyclerView.ItemDecoration] = None def setAdapter(self, adapter: Adapter): self._adapter = adapter def getAdapter(self) -> Optional[Adapter]: return self._adapter def setLayoutManager(self, layoutManager: LayoutManager): self._layout_manager = layoutManager def getLayoutManager(self) -> Optional[LayoutManager]: return self._layout_manager def setItemAnimator(self, animator: ItemAnimator): self._item_animator = animator def getItemAnimator(self) -> Optional[ItemAnimator]: return self._item_animator def addItemDecoration(self, decoration: ItemDecoration, index: int = -1): self._item_decoration = decoration def addOnScrollListener(self, listener: OnScrollListener): self._scroll_listeners.append(listener) def removeOnScrollListener(self, listener: OnScrollListener): self._scroll_listeners = [l for l in self._scroll_listeners if l is not listener] def clearOnScrollListeners(self): self._scroll_listeners.clear() def scrollToPosition(self, position: int): pass def smoothScrollToPosition(self, position: int): pass def toString(self) -> str: return f"RecyclerView(adapter={'set' if self._adapter else 'null'})" # ═══════════════════════════════════════════════════════════════ # PagerAdapter # ═══════════════════════════════════════════════════════════════ class PagerAdapter(Stub): """PagerAdapter — 页面适配器""" POSITION_UNCHANGED = PAGER_POSITION_UNCHANGED POSITION_NONE = PAGER_POSITION_NONE def __init__(self): super().__init__() self._observers: List[Any] = [] def getCount(self) -> int: return 0 def instantiateItem(self, container: Any, position: int) -> Any: return None def destroyItem(self, container: Any, position: int, obj: Any): pass def isViewFromObject(self, view: Any, obj: Any) -> bool: return False def getPageTitle(self, position: int) -> Optional[str]: return None def getPageWidth(self, position: int) -> float: return 1.0 def getItemPosition(self, obj: Any) -> int: return PagerAdapter.POSITION_UNCHANGED def startUpdate(self, container: Any): pass def finishUpdate(self, container: Any): pass def registerDataSetObserver(self, observer: Any): self._observers.append(observer) def unregisterDataSetObserver(self, observer: Any): self._observers = [o for o in self._observers if o is not observer] def notifyDataSetChanged(self): for o in self._observers: if hasattr(o, 'onChanged'): o.onChanged() def toString(self) -> str: return f"PagerAdapter(count={self.getCount()})" # ═══════════════════════════════════════════════════════════════ # FragmentPagerAdapter # ═══════════════════════════════════════════════════════════════ class FragmentPagerAdapter(PagerAdapter): """FragmentPagerAdapter — Fragment 页面适配器""" BEHAVIOR_SET_USER_VISIBLE_HINT = 0 BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1 def __init__(self, fm: Any = None, behavior: int = BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT): super().__init__() self._fm = fm self._behavior = behavior self._fragments: Dict[int, Any] = {} def getItem(self, position: int) -> Any: raise NotImplementedError def instantiateItem(self, container: Any, position: int) -> Any: fragment = self.getItem(position) self._fragments[position] = fragment return fragment def destroyItem(self, container: Any, position: int, obj: Any): self._fragments.pop(position, None) def isViewFromObject(self, view: Any, obj: Any) -> bool: if hasattr(obj, 'getView'): return obj.getView() is view return False def getPageTitle(self, position: int) -> Optional[str]: return None def getItemId(self, position: int) -> int: return position def toString(self) -> str: return f"FragmentPagerAdapter(count={self.getCount()})" # ═══════════════════════════════════════════════════════════════ # FragmentStatePagerAdapter # ═══════════════════════════════════════════════════════════════ class FragmentStatePagerAdapter(FragmentPagerAdapter): """FragmentStatePagerAdapter — Fragment 状态页面适配器""" def __init__(self, fm: Any = None, behavior: int = FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT): super().__init__(fm=fm, behavior=behavior) self._saved_states: Dict[int, Any] = {} def saveState(self, position: int) -> Any: state = self._saved_states.get(position) self._fragments.pop(position, None) return state def restoreState(self, state: Any, loader: Any): pass def instantiateItem(self, container: Any, position: int) -> Any: return super().instantiateItem(container, position) def destroyItem(self, container: Any, position: int, obj: Any): state = self.saveState(position) if state: self._saved_states[position] = state super().destroyItem(container, position, obj) def toString(self) -> str: return f"FragmentStatePagerAdapter(count={self.getCount()})" # ═══════════════════════════════════════════════════════════════ # PagerTitleStrip / PagerTabStrip # ═══════════════════════════════════════════════════════════════ class PagerTitleStrip(Stub): """PagerTitleStrip — 页面标题条""" def __init__(self, context: Any = None): super().__init__() self._text_spacing = 16 self._nonprimary_alpha = 0.6 self._current_page = 0 self._adapter: Optional[PagerAdapter] = None def setAdapter(self, adapter: PagerAdapter): self._adapter = adapter def getAdapter(self) -> Optional[PagerAdapter]: return self._adapter def setTextSpacing(self, spacingPixels: int): self._text_spacing = spacingPixels def getTextSpacing(self) -> int: return self._text_spacing def updateTitle(self, position: int, adapter: PagerAdapter): self._current_page = position def requestLayout(self): pass def toString(self) -> str: return f"PagerTitleStrip(page={self._current_page})" class PagerTabStrip(PagerTitleStrip): """PagerTabStrip — 页面标签条""" def __init__(self, context: Any = None): super().__init__(context=context) self._tab_indicator_color = 0 self._tab_spacing = 8 self._draw_full_underline = False self._underline_height = 2 self._tab_padding = 16 def setTabIndicatorColor(self, color: int): self._tab_indicator_color = color def getTabIndicatorColor(self) -> int: return self._tab_indicator_color def setDrawFullUnderline(self, draw: bool): self._draw_full_underline = draw def isDrawFullUnderline(self) -> bool: return self._draw_full_underline def setUnderlineHeight(self, height: int): self._underline_height = height def getUnderlineHeight(self) -> int: return self._underline_height def setTabPadding(self, padding: int): self._tab_padding = padding def getTabPadding(self) -> int: return self._tab_padding def toString(self) -> str: return f"PagerTabStrip(page={self._current_page})"