核心类方法补全: - Activity: +20方法 (requestWindowFeature, setTitle/getTitle, onKeyDown/onKeyUp, enterPictureInPictureMode, getReferrer, isTaskRoot, navigateUpTo等) - Fragment: +15方法 (getChildFragmentManager, getParentFragment, requireContext/requireActivity, setMenuVisibility等) - Intent: +20方法 (getParcelableExtra, setComponent/getComponent, getDataString, getScheme, putExtras等) - View: +20方法 (setLabelFor, setRotationX/Y, setForeground, setBackgroundTintList等) - KeyEvent: +7方法 (getCharacters, isSystem, isPrintingKey, isModifierKey, startTracking等) - Paint: +12方法 (setStrokeCap/Join, getTextBounds, setBlendMode, setLetterSpacing等) - Notification.Builder: +10方法 (setProgress, setShowWhen, setOnlyAlertOnce, setSound等) 存根转真实实现: - TrafficStats: 读取 /proc/net/dev 返回真实网络流量 - RecyclerView.Adapter: 观察者模式触发通知 - BaseAdapter: 观察者模式触发通知 - ExifInterface: 使用PIL实现图片翻转/旋转 - Process: 使用os.kill实现进程信号 - FileUtils: 真实文件I/O - SharedPreferences: 监听器模式 - TelephonyManager.listen: 维护监听器列表 - ScrollView.smoothScrollTo: 更新滚动位置 Exception体系扩展: - 新增15个Exception/Error类 (ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchElementException, AssertionError, OutOfMemoryError, StackOverflowError, NoClassDefFoundError, UnsatisfiedLinkError, LinkageError, VerifyError, AbstractMethodError, IncompatibleClassChangeError, ExceptionInInitializerError) Math/System/Thread/StringBuilder/Integer增强: - Math: +20方法 (subtractExact, multiplyExact, toIntExact, floorDiv/floorMod, fma等) - System: getProperties/setProperties/mapLibraryName/getLogger - Thread: +10方法 (getUncaughtExceptionHandler, getAllStackTraces, getStackTrace, holdLock等) - StringBuilder: +7方法 (ensureCapacity, trimToSize, setLength, subSequence等) - Integer: +8静态方法 (compare, compareUnsigned, divideUnsigned, sum, max, min等) 修复: - app_fragment.py: 使用java.lang.IllegalStateException替代本地定义 - content_intent.py: Intent.setData/getScheme正确从Uri提取scheme - view_ext.py: KeyEvent继承view.KeyEvent获取所有KEYCODE常量 - __init__.py: 补全Fragment/KeyEvent/MotionEvent/TrafficStats/RecyclerView等导出 统计: 221模块, 3660类, 30826方法, 180217行
1052 lines
35 KiB
Python
1052 lines
35 KiB
Python
"""
|
|
Android Fragment API — Fragment, FragmentManager, FragmentTransaction, etc.
|
|
方法签名完全对齐 Android SDK
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import uuid
|
|
import threading
|
|
from typing import Any, Dict, List, Optional, Set, Tuple, Callable
|
|
from enum import IntEnum
|
|
|
|
from .._core import Stub, AndroidOnlyError
|
|
from ..java.lang import RuntimeException, IllegalArgumentException, IllegalStateException
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# 常量
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
# TRANSIT_* 常量
|
|
TRANSIT_NONE = 0
|
|
TRANSIT_FRAGMENT_OPEN = 1
|
|
TRANSIT_FRAGMENT_CLOSE = 2
|
|
TRANSIT_FRAGMENT_FADE = 3
|
|
TRANSIT_UNSET = -1
|
|
TRANSIT_ENTER_MASK = 0x1000
|
|
TRANSIT_EXIT_MASK = 0x2000
|
|
|
|
# TRANSACTION_* 常量
|
|
TRANSACTION_NONE = 0
|
|
TRANSACTION_ADD = 1
|
|
TRANSACTION_REMOVE = 2
|
|
TRANSACTION_REPLACE = 3
|
|
TRANSACTION_SHOW = 4
|
|
TRANSACTION_HIDE = 5
|
|
TRANSACTION_ATTACH = 6
|
|
TRANSACTION_DETACH = 7
|
|
TRANSACTION_SET_PRIMARY_NAV = 8
|
|
|
|
# OP_* 操作常量 (内部)
|
|
_OP_NONE = 0
|
|
_OP_ADD = 1
|
|
_OP_REPLACE = 2
|
|
_OP_REMOVE = 3
|
|
_OP_HIDE = 4
|
|
_OP_SHOW = 5
|
|
_OP_DETACH = 6
|
|
_OP_ATTACH = 7
|
|
_OP_SET_PRIMARY_NAV = 8
|
|
|
|
# Fragment 常量
|
|
Fragment_USE_DEFAULT_TRANSITION = 0
|
|
FRAGMENT_RESULT_CANCELED = 0
|
|
FRAGMENT_RESULT_OK = -1
|
|
|
|
# FragmentManager 常量
|
|
POP_BACK_STACK_INCLUSIVE = 1
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# Fragment
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class Fragment(Stub):
|
|
"""Fragment — 片段基类 (桌面存根)"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._mCalled = False
|
|
self._mTag: Optional[str] = None
|
|
self._mFragmentId = 0
|
|
self._mContainerId = 0
|
|
self._mView: Optional[Any] = None
|
|
self._mArguments: Optional[Any] = None
|
|
self._mHidden = False
|
|
self._mDetached = False
|
|
self._mRemoving = False
|
|
self._mInLayout = False
|
|
self._mMenuVisible = True
|
|
self._mHasMenu = False
|
|
self._mRetainInstance = False
|
|
self._mUserVisibleHint = True
|
|
self._mState = 0
|
|
self._mSavedState: Optional[Any] = None
|
|
self._mActivity: Optional["FragmentActivity"] = None
|
|
self._mHost: Optional["FragmentHostCallback"] = None
|
|
self._mFragmentManager: Optional["FragmentManager"] = None
|
|
self._mChildFragmentManager: Optional["FragmentManager"] = None
|
|
self._mParentFragment: Optional["Fragment"] = None
|
|
self._mTargetFragment: Optional["Fragment"] = None
|
|
self._mTargetRequestCode = 0
|
|
self._mNextAnim = 0
|
|
self._mEnterTransition: Optional[Any] = None
|
|
self._mExitTransition: Optional[Any] = None
|
|
self._mSharedElementEnterTransition: Optional[Any] = None
|
|
self._mSharedElementExitTransition: Optional[Any] = None
|
|
self._mAllowEnterTransitionOverlap: Optional[bool] = None
|
|
self._mAllowReturnTransitionOverlap: Optional[bool] = None
|
|
self._mReenterTransition: Optional[Any] = None
|
|
self._mReturnTransition: Optional[Any] = None
|
|
self._mSharedElementReturnTransition: Optional[Any] = None
|
|
self._mSharedElementReenterTransition: Optional[Any] = None
|
|
self._mLifecycleRegistry: Optional[Any] = None
|
|
self._mViewModelStore: Optional[Any] = None
|
|
self._mMaxState: Optional[str] = None
|
|
self._mInitialLifecycleState: Optional[int] = None
|
|
self._mPrimaryNavigationFragment = False
|
|
self._mIsNewlyAdded = False
|
|
self._mIsCreated = False
|
|
self._mIsViewCreated = False
|
|
self._mIsStateSaved = False
|
|
self._mIsStateSavedBefore = False
|
|
self._mFragmentTransitionState = 0
|
|
self._mInTransition = False
|
|
self._mPostponedHandler: Optional[Any] = None
|
|
self._mAnimationInfo: Optional[Any] = None
|
|
self._mDebug = False
|
|
self._mCalledForTransition = False
|
|
self._mHiddenChanged = False
|
|
self._mAnimationResId = 0
|
|
self._mContainer: Optional["FragmentContainer"] = None
|
|
self._mFactory: Optional[Any] = None
|
|
self._mRequestPermissionsResult: List[Tuple[int, List[str], List[int]]] = []
|
|
self._mResultListeners: List[Any] = []
|
|
|
|
def getActivity(self) -> Optional["FragmentActivity"]:
|
|
return self._mActivity
|
|
|
|
def getHost(self) -> Optional["FragmentHostCallback"]:
|
|
return self._mHost
|
|
|
|
def getFragmentManager(self) -> Optional["FragmentManager"]:
|
|
return self._mFragmentManager
|
|
|
|
def getChildFragmentManager(self) -> Optional["FragmentManager"]:
|
|
if self._mChildFragmentManager is None:
|
|
from .._core import Stub as _Stub
|
|
self._mChildFragmentManager = FragmentManager()
|
|
return self._mChildFragmentManager
|
|
|
|
def getParentFragment(self) -> Optional["Fragment"]:
|
|
return self._mParentFragment
|
|
|
|
def getTag(self) -> Optional[str]:
|
|
return self._mTag
|
|
|
|
def getId(self) -> int:
|
|
return self._mFragmentId
|
|
|
|
def getView(self) -> Optional[Any]:
|
|
return self._mView
|
|
|
|
def getArguments(self) -> Optional[Any]:
|
|
return self._mArguments
|
|
|
|
def setArguments(self, args: Any) -> None:
|
|
if self._mState > 0:
|
|
raise IllegalStateException("Fragment already active")
|
|
self._mArguments = args
|
|
|
|
def isAdded(self) -> bool:
|
|
return self._mActivity is not None and self._mState > 0
|
|
|
|
def isDetached(self) -> bool:
|
|
return self._mDetached
|
|
|
|
def isRemoving(self) -> bool:
|
|
return self._mRemoving
|
|
|
|
def isInLayout(self) -> bool:
|
|
return self._mInLayout
|
|
|
|
def isResumed(self) -> bool:
|
|
return self._mState >= 7
|
|
|
|
def isVisible(self) -> bool:
|
|
return (not self._mHidden) and self.isAdded() and self._mView is not None
|
|
|
|
def isHidden(self) -> bool:
|
|
return self._mHidden
|
|
|
|
def isMenuVisible(self) -> bool:
|
|
return self._mMenuVisible
|
|
|
|
def getUserVisibleHint(self) -> bool:
|
|
return self._mUserVisibleHint
|
|
|
|
def setUserVisibleHint(self, isVisible: bool) -> None:
|
|
self._mUserVisibleHint = isVisible
|
|
self._mHiddenChanged = not isVisible
|
|
|
|
def getRetainInstance(self) -> bool:
|
|
return self._mRetainInstance
|
|
|
|
def setRetainInstance(self, retain: bool) -> None:
|
|
self._mRetainInstance = retain
|
|
|
|
def hasOptionsMenu(self) -> bool:
|
|
return self._mHasMenu
|
|
|
|
def setHasOptionsMenu(self, hasMenu: bool) -> None:
|
|
self._mHasMenu = hasMenu
|
|
|
|
def setMenuVisibility(self, menuVisible: bool) -> None:
|
|
self._mMenuVisible = menuVisible
|
|
|
|
def getTargetFragment(self) -> Optional["Fragment"]:
|
|
return self._mTargetFragment
|
|
|
|
def setTargetFragment(self, fragment: Optional["Fragment"], requestCode: int) -> None:
|
|
self._mTargetFragment = fragment
|
|
self._mTargetRequestCode = requestCode
|
|
|
|
def getTargetRequestCode(self) -> int:
|
|
return self._mTargetRequestCode
|
|
|
|
def getContext(self) -> Optional[Any]:
|
|
return self._mActivity
|
|
|
|
def getResources(self) -> Optional[Any]:
|
|
if self._mActivity:
|
|
return self._mActivity.getResources()
|
|
return None
|
|
|
|
def requireActivity(self) -> "FragmentActivity":
|
|
if self._mActivity is None:
|
|
raise IllegalStateException("Fragment not attached to Activity")
|
|
return self._mActivity
|
|
|
|
def requireFragmentManager(self) -> "FragmentManager":
|
|
if self._mFragmentManager is None:
|
|
raise IllegalStateException("Fragment not attached to FragmentManager")
|
|
return self._mFragmentManager
|
|
|
|
def requireContext(self) -> Any:
|
|
ctx = self.getContext()
|
|
if ctx is None:
|
|
raise IllegalStateException("Fragment not attached to a context")
|
|
return ctx
|
|
|
|
def requireView(self) -> Any:
|
|
view = self.getView()
|
|
if view is None:
|
|
raise IllegalStateException("Fragment does not have a view")
|
|
return view
|
|
|
|
def requireHost(self) -> "FragmentHostCallback":
|
|
if self._mHost is None:
|
|
raise IllegalStateException("Fragment not attached to host")
|
|
return self._mHost
|
|
|
|
def isStateSaved(self) -> bool:
|
|
return self._mIsStateSaved
|
|
|
|
def getLifecycle(self) -> Optional[Any]:
|
|
return self._mLifecycleRegistry
|
|
|
|
def getViewModelStore(self) -> Optional[Any]:
|
|
return self._mViewModelStore
|
|
|
|
def postponeEnterTransition(self) -> None:
|
|
self._mPostponedHandler = True
|
|
|
|
def startPostponedEnterTransition(self) -> None:
|
|
self._mPostponedHandler = None
|
|
|
|
def getEnterTransition(self) -> Optional[Any]:
|
|
return self._mEnterTransition
|
|
|
|
def setEnterTransition(self, transition: Any) -> None:
|
|
self._mEnterTransition = transition
|
|
|
|
def getExitTransition(self) -> Optional[Any]:
|
|
return self._mExitTransition
|
|
|
|
def setExitTransition(self, transition: Any) -> None:
|
|
self._mExitTransition = transition
|
|
|
|
def getSharedElementEnterTransition(self) -> Optional[Any]:
|
|
return self._mSharedElementEnterTransition
|
|
|
|
def setSharedElementEnterTransition(self, transition: Any) -> None:
|
|
self._mSharedElementEnterTransition = transition
|
|
|
|
def getSharedElementExitTransition(self) -> Optional[Any]:
|
|
return self._mSharedElementExitTransition
|
|
|
|
def setSharedElementExitTransition(self, transition: Any) -> None:
|
|
self._mSharedElementExitTransition = transition
|
|
|
|
def getReenterTransition(self) -> Optional[Any]:
|
|
return self._mReenterTransition or self._mEnterTransition
|
|
|
|
def setReenterTransition(self, transition: Any) -> None:
|
|
self._mReenterTransition = transition
|
|
|
|
def getReturnTransition(self) -> Optional[Any]:
|
|
return self._mReturnTransition or self._mExitTransition
|
|
|
|
def setReturnTransition(self, transition: Any) -> None:
|
|
self._mReturnTransition = transition
|
|
|
|
def getSharedElementReturnTransition(self) -> Optional[Any]:
|
|
return self._mSharedElementReturnTransition or self._mSharedElementEnterTransition
|
|
|
|
def setSharedElementReturnTransition(self, transition: Any) -> None:
|
|
self._mSharedElementReturnTransition = transition
|
|
|
|
def getSharedElementReenterTransition(self) -> Optional[Any]:
|
|
return self._mSharedElementReenterTransition or self._mSharedElementExitTransition
|
|
|
|
def setSharedElementReenterTransition(self, transition: Any) -> None:
|
|
self._mSharedElementReenterTransition = transition
|
|
|
|
def getAllowEnterTransitionOverlap(self) -> bool:
|
|
return self._mAllowEnterTransitionOverlap is not False
|
|
|
|
def setAllowEnterTransitionOverlap(self, allow: bool) -> None:
|
|
self._mAllowEnterTransitionOverlap = allow
|
|
|
|
def getAllowReturnTransitionOverlap(self) -> bool:
|
|
return self._mAllowReturnTransitionOverlap is not False
|
|
|
|
def setAllowReturnTransitionOverlap(self, allow: bool) -> None:
|
|
self._mAllowReturnTransitionOverlap = allow
|
|
|
|
def isInBackStack(self) -> bool:
|
|
return self._mFragmentManager is not None
|
|
|
|
def getString(self, resId: int, *formatArgs: Any) -> str:
|
|
return f"string_{resId}"
|
|
|
|
def getText(self, resId: int) -> str:
|
|
return f"text_{resId}"
|
|
|
|
def getInt(self, resId: int) -> int:
|
|
return 0
|
|
|
|
def getBoolean(self, resId: int) -> bool:
|
|
return False
|
|
|
|
def instantiate(self, context: Any, fname: str, args: Optional[Any] = None) -> "Fragment":
|
|
return Fragment()
|
|
|
|
# ── 生命周期 ──
|
|
def onAttach(self, context: Any) -> None:
|
|
self._mCalled = True
|
|
|
|
def onCreate(self, savedInstanceState: Optional[Any]) -> None:
|
|
self._mCalled = True
|
|
self._mIsCreated = True
|
|
|
|
def onCreateView(self, inflater: Any, container: Any, savedInstanceState: Optional[Any]) -> Optional[Any]:
|
|
self._mCalled = True
|
|
return None
|
|
|
|
def onViewCreated(self, view: Any, savedInstanceState: Optional[Any]) -> None:
|
|
self._mCalled = True
|
|
self._mIsViewCreated = True
|
|
|
|
def onActivityCreated(self, savedInstanceState: Optional[Any]) -> None:
|
|
self._mCalled = True
|
|
|
|
def onViewStateRestored(self, savedInstanceState: Optional[Any]) -> None:
|
|
self._mCalled = True
|
|
|
|
def onStart(self) -> None:
|
|
self._mCalled = True
|
|
|
|
def onResume(self) -> None:
|
|
self._mCalled = True
|
|
|
|
def onPause(self) -> None:
|
|
self._mCalled = True
|
|
|
|
def onStop(self) -> None:
|
|
self._mCalled = True
|
|
|
|
def onDestroyView(self) -> None:
|
|
self._mCalled = True
|
|
self._mIsViewCreated = False
|
|
|
|
def onDestroy(self) -> None:
|
|
self._mCalled = True
|
|
self._mIsCreated = False
|
|
|
|
def onDetach(self) -> None:
|
|
self._mCalled = True
|
|
|
|
def onSaveInstanceState(self, outState: Any) -> None:
|
|
pass
|
|
|
|
def onMultiWindowModeChanged(self, isInMultiWindowMode: bool, newConfig: Any) -> None:
|
|
pass
|
|
|
|
def onPictureInPictureModeChanged(self, isInPictureInPictureMode: bool, newConfig: Any) -> None:
|
|
pass
|
|
|
|
def onConfigurationChanged(self, newConfig: Any) -> None:
|
|
pass
|
|
|
|
def onLowMemory(self) -> None:
|
|
pass
|
|
|
|
def onHiddenChanged(self, hidden: bool) -> None:
|
|
pass
|
|
|
|
def onAttachFragment(self, childFragment: "Fragment") -> None:
|
|
pass
|
|
|
|
def dump(self, prefix: str, fd: Any, writer: Any, args: List[str]) -> None:
|
|
pass
|
|
|
|
def registerForActivityResult(self, contract: Any, callback: Any) -> Any:
|
|
return None
|
|
|
|
def unregisterForActivityResult(self, token: Any) -> None:
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return f"Fragment({self._mTag or hex(id(self))})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# FragmentManager
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class FragmentManager(Stub):
|
|
"""FragmentManager — 片段管理器"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._lock = threading.Lock()
|
|
self._fragments: Dict[str, Fragment] = {}
|
|
self._back_stack: List["FragmentTransaction"] = []
|
|
self._back_stack_indices: Dict[int, str] = {}
|
|
self._next_index = 0
|
|
self._primary_nav_fragment: Optional[Fragment] = None
|
|
self._fragment_container: Optional["FragmentContainer"] = None
|
|
|
|
def beginTransaction(self) -> "FragmentTransaction":
|
|
return FragmentTransaction(self)
|
|
|
|
def executePendingTransactions(self) -> bool:
|
|
return True
|
|
|
|
def findFragmentById(self, id: int) -> Optional[Fragment]:
|
|
with self._lock:
|
|
for frag in self._fragments.values():
|
|
if frag.getId() == id:
|
|
return frag
|
|
return None
|
|
|
|
def findFragmentByTag(self, tag: str) -> Optional[Fragment]:
|
|
with self._lock:
|
|
return self._fragments.get(tag)
|
|
|
|
def popBackStack(self) -> None:
|
|
with self._lock:
|
|
if self._back_stack:
|
|
trans = self._back_stack.pop()
|
|
trans._reverse()
|
|
|
|
def popBackStackImmediate(self, name: Optional[str] = None, flags: int = 0) -> bool:
|
|
self.popBackStack()
|
|
return True
|
|
|
|
def popBackStack(
|
|
self, name: Optional[str], flags: int
|
|
) -> None:
|
|
with self._lock:
|
|
if name is None:
|
|
if self._back_stack:
|
|
trans = self._back_stack.pop()
|
|
trans._reverse()
|
|
return
|
|
idx = -1
|
|
for i, t in enumerate(self._back_stack):
|
|
if t._name == name:
|
|
idx = i
|
|
break
|
|
if idx >= 0:
|
|
inclusive = (flags & POP_BACK_STACK_INCLUSIVE) != 0
|
|
start = idx if inclusive else idx + 1
|
|
to_remove = self._back_stack[start:]
|
|
self._back_stack = self._back_stack[:start]
|
|
for t in reversed(to_remove):
|
|
t._reverse()
|
|
|
|
def getBackStackEntryCount(self) -> int:
|
|
with self._lock:
|
|
return len(self._back_stack)
|
|
|
|
def getBackStackEntryAt(self, index: int) -> Optional[Any]:
|
|
with self._lock:
|
|
if 0 <= index < len(self._back_stack):
|
|
return self._back_stack[index]
|
|
return None
|
|
|
|
def saveFragmentInstanceState(self, fragment: Fragment) -> Optional[Any]:
|
|
return None
|
|
|
|
def isDestroyed(self) -> bool:
|
|
return False
|
|
|
|
def isStateSaved(self) -> bool:
|
|
return False
|
|
|
|
def getFragments(self) -> List[Fragment]:
|
|
with self._lock:
|
|
return list(self._fragments.values())
|
|
|
|
def getFragment(self, bundle: Any, key: str) -> Optional[Fragment]:
|
|
return None
|
|
|
|
def putFragment(self, bundle: Any, key: str, fragment: Fragment) -> None:
|
|
pass
|
|
|
|
def getPrimaryNavigationFragment(self) -> Optional[Fragment]:
|
|
return self._primary_nav_fragment
|
|
|
|
def registerFragmentLifecycleCallbacks(self, cb: Any, recursive: bool) -> None:
|
|
pass
|
|
|
|
def unregisterFragmentLifecycleCallbacks(self, cb: Any) -> None:
|
|
pass
|
|
|
|
def isPrimaryNavigation(self, fragment: Fragment) -> bool:
|
|
return fragment == self._primary_nav_fragment
|
|
|
|
def toString(self) -> str:
|
|
with self._lock:
|
|
return f"FragmentManager(fragments={len(self._fragments)}, backstack={len(self._back_stack)})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# FragmentTransaction
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class FragmentTransaction(Stub):
|
|
"""FragmentTransaction — 片段事务"""
|
|
|
|
TRANSIT_ENTER_MASK = TRANSIT_ENTER_MASK
|
|
TRANSIT_EXIT_MASK = TRANSIT_EXIT_MASK
|
|
TRANSIT_UNSET = TRANSIT_UNSET
|
|
TRANSIT_NONE = TRANSIT_NONE
|
|
TRANSIT_FRAGMENT_OPEN = TRANSIT_FRAGMENT_OPEN
|
|
TRANSIT_FRAGMENT_CLOSE = TRANSIT_FRAGMENT_CLOSE
|
|
TRANSIT_FRAGMENT_FADE = TRANSIT_FRAGMENT_FADE
|
|
|
|
def __init__(self, manager: "FragmentManager"):
|
|
super().__init__()
|
|
self._manager = manager
|
|
self._ops: List[Dict[str, Any]] = []
|
|
self._name: Optional[str] = None
|
|
self._transition = TRANSIT_NONE
|
|
self._transition_style = 0
|
|
self._transition_shared = False
|
|
self._allow_add_to_back_stack = True
|
|
self._add_to_back_stack = False
|
|
self._is_reordering_allowed = False
|
|
self._bread_crumb_title_res = 0
|
|
self._bread_crumb_title: Optional[str] = None
|
|
self._mCommitListener: Optional[Any] = None
|
|
|
|
def add(self, containerViewId: Any = 0, fragment: Optional[Any] = None, tag: Optional[str] = None) -> "FragmentTransaction":
|
|
if fragment is None and not isinstance(containerViewId, int):
|
|
fragment = containerViewId
|
|
containerViewId = 0
|
|
self._ops.append({
|
|
"op": _OP_ADD,
|
|
"fragment": fragment,
|
|
"containerId": int(containerViewId) if isinstance(containerViewId, int) else 0,
|
|
"tag": tag,
|
|
})
|
|
if tag:
|
|
fragment._mTag = tag
|
|
return self
|
|
|
|
def replace(self, containerViewId: int, fragment: Fragment, tag: Optional[str] = None) -> "FragmentTransaction":
|
|
self._ops.append({
|
|
"op": _OP_REPLACE,
|
|
"fragment": fragment,
|
|
"containerId": containerViewId,
|
|
"tag": tag,
|
|
})
|
|
if tag:
|
|
fragment._mTag = tag
|
|
return self
|
|
|
|
def remove(self, fragment: Fragment) -> "FragmentTransaction":
|
|
self._ops.append({"op": _OP_REMOVE, "fragment": fragment})
|
|
return self
|
|
|
|
def hide(self, fragment: Fragment) -> "FragmentTransaction":
|
|
self._ops.append({"op": _OP_HIDE, "fragment": fragment})
|
|
return self
|
|
|
|
def show(self, fragment: Fragment) -> "FragmentTransaction":
|
|
self._ops.append({"op": _OP_SHOW, "fragment": fragment})
|
|
return self
|
|
|
|
def detach(self, fragment: Fragment) -> "FragmentTransaction":
|
|
self._ops.append({"op": _OP_DETACH, "fragment": fragment})
|
|
return self
|
|
|
|
def attach(self, fragment: Fragment) -> "FragmentTransaction":
|
|
self._ops.append({"op": _OP_ATTACH, "fragment": fragment})
|
|
return self
|
|
|
|
def setPrimaryNavigationFragment(self, fragment: Fragment) -> "FragmentTransaction":
|
|
self._ops.append({"op": _OP_SET_PRIMARY_NAV, "fragment": fragment})
|
|
return self
|
|
|
|
def addToBackStack(self, name: Optional[str] = None) -> "FragmentTransaction":
|
|
self._add_to_back_stack = True
|
|
self._name = name
|
|
return self
|
|
|
|
def setTransition(self, transit: int) -> "FragmentTransaction":
|
|
self._transition = transit
|
|
return self
|
|
|
|
def setTransitionStyle(self, styleRes: int) -> "FragmentTransaction":
|
|
self._transition_style = styleRes
|
|
return self
|
|
|
|
def setAllowOptimization(self, allow: bool) -> "FragmentTransaction":
|
|
self._is_reordering_allowed = allow
|
|
return self
|
|
|
|
def setReorderingAllowed(self, allowed: bool) -> "FragmentTransaction":
|
|
self._is_reordering_allowed = allowed
|
|
return self
|
|
|
|
def setBreadCrumbTitle(self, titleOrRes: Any) -> "FragmentTransaction":
|
|
if isinstance(titleOrRes, int):
|
|
self._bread_crumb_title_res = titleOrRes
|
|
else:
|
|
self._bread_crumb_title = str(titleOrRes)
|
|
return self
|
|
|
|
def runOnCommit(self, runnable: Callable[[], None]) -> "FragmentTransaction":
|
|
self._mCommitListener = runnable
|
|
return self
|
|
|
|
def commit(self) -> int:
|
|
with self._manager._lock:
|
|
entry_id = self._manager._next_index
|
|
self._manager._next_index += 1
|
|
self._commit_ops()
|
|
if self._add_to_back_stack:
|
|
self._manager._back_stack.append(self)
|
|
return entry_id
|
|
|
|
def commitNow(self) -> None:
|
|
self.commit()
|
|
|
|
def commitAllowingStateLoss(self) -> int:
|
|
return self.commit()
|
|
|
|
def _commit_ops(self) -> None:
|
|
for op in self._ops:
|
|
frag = op["fragment"]
|
|
tag = op.get("tag") or frag._mTag
|
|
if op["op"] == _OP_ADD or op["op"] == _OP_REPLACE:
|
|
if tag:
|
|
self._manager._fragments[tag] = frag
|
|
frag._mFragmentManager = self._manager
|
|
elif op["op"] == _OP_REMOVE:
|
|
if tag and tag in self._manager._fragments:
|
|
del self._manager._fragments[tag]
|
|
elif op["op"] == _OP_SET_PRIMARY_NAV:
|
|
self._manager._primary_nav_fragment = frag
|
|
|
|
def _reverse(self) -> None:
|
|
for op in reversed(self._ops):
|
|
frag = op["fragment"]
|
|
tag = frag._mTag
|
|
if op["op"] == _OP_ADD:
|
|
if tag and tag in self._manager._fragments:
|
|
del self._manager._fragments[tag]
|
|
elif op["op"] == _OP_REMOVE:
|
|
if tag:
|
|
self._manager._fragments[tag] = frag
|
|
|
|
def toString(self) -> str:
|
|
return f"FragmentTransaction(ops={len(self._ops)}, backstack={self._add_to_back_stack})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# FragmentActivity
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class FragmentActivity(Stub):
|
|
"""FragmentActivity — 支持 Fragment 的 Activity"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._mFragments: FragmentController = FragmentController(FragmentManager())
|
|
self._mFragmentManager: FragmentManager = FragmentManager()
|
|
self._mCreated = False
|
|
self._mResumed = False
|
|
self._mStarted = False
|
|
|
|
def getSupportFragmentManager(self) -> FragmentManager:
|
|
return self._mFragmentManager
|
|
|
|
def getSupportFragmentManager(self) -> FragmentManager:
|
|
return self._mFragments.getFragmentManager()
|
|
|
|
def onAttachFragment(self, fragment: Fragment) -> None:
|
|
pass
|
|
|
|
def supportInvalidateOptionsMenu(self) -> None:
|
|
pass
|
|
|
|
def dump(self, prefix: str, fd: Any, writer: Any, args: List[str]) -> None:
|
|
pass
|
|
|
|
def getLifecycle(self) -> Optional[Any]:
|
|
return None
|
|
|
|
def getViewModelStore(self) -> Optional[Any]:
|
|
return None
|
|
|
|
def toString(self) -> str:
|
|
return f"FragmentActivity@{hex(id(self))}"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# FragmentController
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class FragmentController(Stub):
|
|
"""FragmentController — 片段控制器"""
|
|
|
|
def __init__(self, manager: FragmentManager):
|
|
super().__init__()
|
|
self._manager = manager
|
|
|
|
def getFragmentManager(self) -> FragmentManager:
|
|
return self._manager
|
|
|
|
def execPendingActions(self) -> None:
|
|
pass
|
|
|
|
def doLoaderStart(self) -> None:
|
|
pass
|
|
|
|
def doLoaderStop(self, retain: bool) -> None:
|
|
pass
|
|
|
|
def doLoaderRetain(self) -> None:
|
|
pass
|
|
|
|
def doLoaderDestroy(self) -> None:
|
|
pass
|
|
|
|
def noteStateNotSaved(self) -> None:
|
|
pass
|
|
|
|
def saveAllState(self) -> Optional[Any]:
|
|
return None
|
|
|
|
def restoreAllState(self, state: Any) -> None:
|
|
pass
|
|
|
|
def createLoader(self, id: int, bundle: Any, callback: Any) -> Any:
|
|
return None
|
|
|
|
def dispatchCreate(self) -> None:
|
|
pass
|
|
|
|
def dispatchActivityCreated(self) -> None:
|
|
pass
|
|
|
|
def dispatchStart(self) -> None:
|
|
pass
|
|
|
|
def dispatchResume(self) -> None:
|
|
pass
|
|
|
|
def dispatchPause(self) -> None:
|
|
pass
|
|
|
|
def dispatchStop(self) -> None:
|
|
pass
|
|
|
|
def dispatchDestroy(self) -> None:
|
|
pass
|
|
|
|
def dispatchMultiWindowModeChanged(self, isInMultiWindowMode: bool, newConfig: Any) -> None:
|
|
pass
|
|
|
|
def dispatchPictureInPictureModeChanged(self, isInPictureInPictureMode: bool, newConfig: Any) -> None:
|
|
pass
|
|
|
|
def dispatchConfigurationChanged(self, newConfig: Any) -> None:
|
|
pass
|
|
|
|
def dispatchLowMemory(self) -> None:
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return f"FragmentController(manager={self._manager})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# FragmentHostCallback
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class FragmentHostCallback(Stub):
|
|
"""FragmentHostCallback — 片段宿主的回调基类"""
|
|
|
|
def __init__(self, context: Any = None, fragmentManager: Any = None, loaderManager: Any = None):
|
|
super().__init__()
|
|
self._context = context
|
|
self._fragmentManager = fragmentManager
|
|
self._loaderManager = loaderManager
|
|
|
|
def onStartLoadingFragment(self, fragment: Fragment) -> None:
|
|
pass
|
|
|
|
def onDump(self, prefix: str, fd: Any, writer: Any, args: List[str]) -> None:
|
|
pass
|
|
|
|
def onShouldShowRequestPermissionRationale(self, permission: str) -> bool:
|
|
return True
|
|
|
|
def onGetLayoutInflater(self) -> Any:
|
|
return None
|
|
|
|
def onFindViewById(self, id: int) -> Optional[Any]:
|
|
return None
|
|
|
|
def onHasView(self) -> bool:
|
|
return False
|
|
|
|
def onGetWindowAnimations(self) -> int:
|
|
return 0
|
|
|
|
def onHasWindowAnimations(self) -> bool:
|
|
return False
|
|
|
|
def onGetActivityResultRegistry(self) -> Any:
|
|
return None
|
|
|
|
def onAttachFragment(self, fragment: Fragment) -> None:
|
|
pass
|
|
|
|
def onGetHostIdentifier(self) -> Any:
|
|
return None
|
|
|
|
def onValidateRequestPermissionsRequestCode(self, requestCode: int) -> None:
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return f"FragmentHostCallback@{hex(id(self))}"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# FragmentContainer
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class FragmentContainer(Stub):
|
|
"""FragmentContainer — 片段容器接口"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
def instantiate(self, context: Any, className: str, arguments: Optional[Any] = None) -> Fragment:
|
|
return Fragment()
|
|
|
|
def onFindViewById(self, id: int) -> Optional[Any]:
|
|
return None
|
|
|
|
def onHasView(self) -> bool:
|
|
return False
|
|
|
|
def toString(self) -> str:
|
|
return f"FragmentContainer@{hex(id(self))}"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# DialogFragment
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class DialogFragment(Fragment):
|
|
"""DialogFragment — 对话框片段"""
|
|
|
|
STYLE_NORMAL = 0
|
|
STYLE_NO_TITLE = 1
|
|
STYLE_NO_FRAME = 2
|
|
STYLE_NO_INPUT = 3
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._dialog: Optional[Any] = None
|
|
self._style = DialogFragment.STYLE_NORMAL
|
|
self._theme = 0
|
|
self._cancelable = True
|
|
self._showing = False
|
|
self._dismissed = False
|
|
self._dismissed_by_nav = False
|
|
self._shows_dialog = True
|
|
self._mBackStackId = -1
|
|
self._mDialogCanceled = False
|
|
|
|
def setStyle(self, style: int, theme: int = 0) -> None:
|
|
self._style = style
|
|
self._theme = theme
|
|
|
|
def show(self, manager: FragmentManager, tag: str) -> None:
|
|
self._showing = True
|
|
manager.beginTransaction().add(self, tag).commit()
|
|
|
|
def showNow(self, manager: FragmentManager, tag: str) -> None:
|
|
self.show(manager, tag)
|
|
|
|
def dismiss(self) -> None:
|
|
self._dismissed = True
|
|
fm = self.getFragmentManager()
|
|
if fm:
|
|
fm.beginTransaction().remove(self).commit()
|
|
|
|
def dismissAllowingStateLoss(self) -> None:
|
|
self.dismiss()
|
|
|
|
def getDialog(self) -> Optional[Any]:
|
|
return self._dialog
|
|
|
|
def getTheme(self) -> int:
|
|
return self._theme
|
|
|
|
def setCancelable(self, cancelable: bool) -> None:
|
|
self._cancelable = cancelable
|
|
|
|
def isCancelable(self) -> bool:
|
|
return self._cancelable
|
|
|
|
def setShowsDialog(self, showsDialog: bool) -> None:
|
|
self._shows_dialog = showsDialog
|
|
|
|
def getShowsDialog(self) -> bool:
|
|
return self._shows_dialog
|
|
|
|
def onDismiss(self, dialog: Any) -> None:
|
|
pass
|
|
|
|
def onCancel(self, dialog: Any) -> None:
|
|
pass
|
|
|
|
def onCreateDialog(self, savedInstanceState: Optional[Any]) -> Any:
|
|
return None
|
|
|
|
def toString(self) -> str:
|
|
return f"DialogFragment(style={self._style}, showing={self._showing})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# ListFragment
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class ListFragment(Fragment):
|
|
"""ListFragment — 列表片段"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._adapter: Optional[Any] = None
|
|
self._list_view: Optional[Any] = None
|
|
self._selected_position = -1
|
|
self._empty_text: Optional[str] = None
|
|
self._empty_view: Optional[Any] = None
|
|
self._progress_container: Optional[Any] = None
|
|
self._standard_empty_view = False
|
|
self._list_shown = False
|
|
self._list_shown_no_animation = True
|
|
|
|
def getListAdapter(self) -> Optional[Any]:
|
|
return self._adapter
|
|
|
|
def setListAdapter(self, adapter: Any) -> None:
|
|
self._adapter = adapter
|
|
|
|
def getListView(self) -> Optional[Any]:
|
|
return self._list_view
|
|
|
|
def getSelectedItemPosition(self) -> int:
|
|
return self._selected_position
|
|
|
|
def getSelectedItemId(self) -> int:
|
|
return 0
|
|
|
|
def setSelection(self, position: int) -> None:
|
|
self._selected_position = position
|
|
|
|
def setEmptyText(self, text: str) -> None:
|
|
self._empty_text = text
|
|
|
|
def getEmptyText(self) -> Optional[str]:
|
|
return self._empty_text
|
|
|
|
def listViewScrollToTop(self) -> None:
|
|
pass
|
|
|
|
def isListShown(self) -> bool:
|
|
return self._list_shown
|
|
|
|
def setListShown(self, shown: bool) -> None:
|
|
self._list_shown = shown
|
|
self._list_shown_no_animation = True
|
|
|
|
def setListShownNoAnimation(self, shown: bool) -> None:
|
|
self._list_shown = shown
|
|
self._list_shown_no_animation = True
|
|
|
|
def onListItemClick(self, lv: Any, v: Any, position: int, id: int) -> None:
|
|
pass
|
|
|
|
def onListAdapterChanged(self, adapter: Any) -> None:
|
|
pass
|
|
|
|
def toString(self) -> str:
|
|
return f"ListFragment(list_shown={self._list_shown})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# FragmentManagerNonConfig
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class FragmentManagerNonConfig(Stub):
|
|
"""FragmentManagerNonConfig — 非配置保留片段 (已弃用)"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._fragments: List[Fragment] = []
|
|
self._child_non_configs: List["FragmentManagerNonConfig"] = []
|
|
self._view_model_stores: List[Any] = []
|
|
|
|
def getFragments(self) -> List[Fragment]:
|
|
return list(self._fragments)
|
|
|
|
def getChildNonConfigs(self) -> List["FragmentManagerNonConfig"]:
|
|
return list(self._child_non_configs)
|
|
|
|
def getViewModelStores(self) -> List[Any]:
|
|
return list(self._view_model_stores)
|
|
|
|
def toString(self) -> str:
|
|
return f"FragmentManagerNonConfig(fragments={len(self._fragments)})" |