- android/ 167个模块 (app/content/os/view/widget/graphics/media/hardware/net/telephony/provider等) - java/ 35个模块 (lang/io/util/net/nio/security/crypto/sql/beans/rmi/awt等) - javax/ 4个模块 (net/crypto/security/sql) - org/ 5个模块 (json/w3c_dom/xml_sax/xml_pull/apache_http) - dalvik/ 1个模块 (system) - ~3053个类/接口,方法签名完全对齐Android SDK - 桌面跨平台运行 (Windows/macOS/Linux) - 修复所有导入错误和Python关键字冲突
887 lines
29 KiB
Python
887 lines
29 KiB
Python
"""
|
|
Android View Animator 组件 — LayoutAnimationController, AnimationUtils,
|
|
AnimationSet, Interpolator 系列, RotateAnimation, ScaleAnimation,
|
|
TranslateAnimation, AlphaAnimation, GridLayoutAnimationController 等
|
|
方法签名完全对齐 Android SDK
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import math
|
|
import time
|
|
from typing import Any, Callable, Dict, List, Optional, Tuple
|
|
|
|
from .._core import Stub, AndroidOnlyError
|
|
|
|
__all__ = [
|
|
"LayoutAnimationController", "AnimationUtils", "AnimationSet",
|
|
"AnimationScale", "AnimationInterpolator", "CycleInterpolator",
|
|
"AccelerateInterpolator", "DecelerateInterpolator",
|
|
"AccelerateDecelerateInterpolator", "AnticipateInterpolator",
|
|
"OvershootInterpolator", "AnticipateOvershootInterpolator",
|
|
"BounceInterpolator", "LinearInterpolator", "PathInterpolator",
|
|
"RotateAnimation", "ScaleAnimation", "TranslateAnimation",
|
|
"AlphaAnimation", "AnimationDescription",
|
|
"GridLayoutAnimationController",
|
|
]
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# 常量
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
INFINITE = -1
|
|
RESTART = 1
|
|
REVERSE = 2
|
|
|
|
ZORDER_NORMAL = 0
|
|
ZORDER_TOP = 1
|
|
ZORDER_BOTTOM = -1
|
|
|
|
RELATIVE_TO_SELF = 0
|
|
RELATIVE_TO_PARENT = 1
|
|
|
|
FILL_AFTER = 1
|
|
FILL_BEFORE = 2
|
|
FILL_BOTH = 3
|
|
|
|
START_ON_FIRST_FRAME = 4
|
|
ABSOLUTE_TO_SELF = 8
|
|
|
|
ANIMATION_STARTED = 0
|
|
ANIMATION_RUNNING = 1
|
|
ANIMATION_FILLED = 2
|
|
ANIMATION_ENDED = 3
|
|
ANIMATION_CANCELLED = 4
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# AnimationInterpolator
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class AnimationInterpolator(Stub):
|
|
"""AnimationInterpolator — 动画插值器基类"""
|
|
|
|
def getInterpolation(self, input: float) -> float:
|
|
return input
|
|
|
|
def toString(self) -> str:
|
|
return f"{self.__class__.__name__}@{hex(id(self))}"
|
|
|
|
def equals(self, other: Any) -> bool:
|
|
return self is other
|
|
|
|
def hashCode(self) -> int:
|
|
return id(self) & 0x7FFFFFFF
|
|
|
|
|
|
class LinearInterpolator(AnimationInterpolator):
|
|
"""LinearInterpolator — 线性插值器"""
|
|
|
|
def getInterpolation(self, input: float) -> float:
|
|
return input
|
|
|
|
def toString(self) -> str:
|
|
return "LinearInterpolator"
|
|
|
|
|
|
class AccelerateInterpolator(AnimationInterpolator):
|
|
"""AccelerateInterpolator — 加速插值器"""
|
|
|
|
def __init__(self, factor: float = 1.0):
|
|
super().__init__()
|
|
self._factor = factor
|
|
self._double_factor = 2.0 * factor
|
|
|
|
def getInterpolation(self, input: float) -> float:
|
|
if self._factor == 1.0:
|
|
return input * input
|
|
return pow(input, self._double_factor)
|
|
|
|
def toString(self) -> str:
|
|
return f"AccelerateInterpolator(factor={self._factor})"
|
|
|
|
|
|
class DecelerateInterpolator(AnimationInterpolator):
|
|
"""DecelerateInterpolator — 减速插值器"""
|
|
|
|
def __init__(self, factor: float = 1.0):
|
|
super().__init__()
|
|
self._factor = factor
|
|
|
|
def getInterpolation(self, input: float) -> float:
|
|
if self._factor == 1.0:
|
|
return 1.0 - (1.0 - input) * (1.0 - input)
|
|
return 1.0 - pow(1.0 - input, 2.0 * self._factor)
|
|
|
|
def toString(self) -> str:
|
|
return f"DecelerateInterpolator(factor={self._factor})"
|
|
|
|
|
|
class AccelerateDecelerateInterpolator(AnimationInterpolator):
|
|
"""AccelerateDecelerateInterpolator — 加速减速插值器"""
|
|
|
|
def getInterpolation(self, input: float) -> float:
|
|
return float(math.cos((input + 1.0) * math.pi) / 2.0 + 0.5)
|
|
|
|
def toString(self) -> str:
|
|
return "AccelerateDecelerateInterpolator"
|
|
|
|
|
|
class AnticipateInterpolator(AnimationInterpolator):
|
|
"""AnticipateInterpolator — 预期插值器"""
|
|
|
|
def __init__(self, tension: float = 2.0):
|
|
super().__init__()
|
|
self._tension = tension
|
|
|
|
def getInterpolation(self, input: float) -> float:
|
|
return input * input * ((self._tension + 1.0) * input - self._tension)
|
|
|
|
def toString(self) -> str:
|
|
return f"AnticipateInterpolator(tension={self._tension})"
|
|
|
|
|
|
class OvershootInterpolator(AnimationInterpolator):
|
|
"""OvershootInterpolator — 超调插值器"""
|
|
|
|
def __init__(self, tension: float = 2.0):
|
|
super().__init__()
|
|
self._tension = tension
|
|
|
|
def getInterpolation(self, input: float) -> float:
|
|
x = input - 1.0
|
|
return x * x * ((self._tension + 1.0) * x + self._tension) + 1.0
|
|
|
|
def toString(self) -> str:
|
|
return f"OvershootInterpolator(tension={self._tension})"
|
|
|
|
|
|
class AnticipateOvershootInterpolator(AnimationInterpolator):
|
|
"""AnticipateOvershootInterpolator — 预期超调插值器"""
|
|
|
|
def __init__(self, tension: float = 2.0, extraTension: float = 1.5):
|
|
super().__init__()
|
|
self._tension = tension
|
|
self._extra_tension = extraTension
|
|
|
|
def getInterpolation(self, input: float) -> float:
|
|
if input < 0.5:
|
|
x = 2.0 * input
|
|
return 0.5 * x * x * ((self._tension + 1.0) * x - self._tension)
|
|
else:
|
|
x = 2.0 * input - 2.0
|
|
t = self._tension * self._extra_tension
|
|
return 0.5 * (x * x * ((t + 1.0) * x + t) + 2.0)
|
|
|
|
def toString(self) -> str:
|
|
return f"AnticipateOvershootInterpolator(tension={self._tension})"
|
|
|
|
|
|
class BounceInterpolator(AnimationInterpolator):
|
|
"""BounceInterpolator — 弹跳插值器"""
|
|
|
|
def getInterpolation(self, input: float) -> float:
|
|
x = input
|
|
for i in range(4):
|
|
duration = pow(2.0, -i) * 0.6
|
|
if x < duration:
|
|
scale = 0.5 / duration
|
|
return scale * x * (duration - x) * 8.0 + (1.0 - 1.0 / pow(2.0, i))
|
|
x -= duration
|
|
return 0.0
|
|
|
|
def toString(self) -> str:
|
|
return "BounceInterpolator"
|
|
|
|
|
|
class CycleInterpolator(AnimationInterpolator):
|
|
"""CycleInterpolator — 周期插值器"""
|
|
|
|
def __init__(self, cycles: float = 1.0):
|
|
super().__init__()
|
|
self._cycles = cycles
|
|
|
|
def getInterpolation(self, input: float) -> float:
|
|
return float(math.sin(2.0 * math.pi * self._cycles * input))
|
|
|
|
def toString(self) -> str:
|
|
return f"CycleInterpolator(cycles={self._cycles})"
|
|
|
|
|
|
class PathInterpolator(AnimationInterpolator):
|
|
"""PathInterpolator — 路径插值器"""
|
|
|
|
def __init__(self, controlX1: float = 0.0, controlY1: float = 0.0,
|
|
controlX2: float = 1.0, controlY2: float = 1.0):
|
|
super().__init__()
|
|
self._cx1 = controlX1
|
|
self._cy1 = controlY1
|
|
self._cx2 = controlX2
|
|
self._cy2 = controlY2
|
|
|
|
def getInterpolation(self, input: float) -> float:
|
|
t = input
|
|
return (1.0 - t) * (1.0 - t) * (1.0 - t) * 0.0 + \
|
|
3.0 * (1.0 - t) * (1.0 - t) * t * self._cy1 + \
|
|
3.0 * (1.0 - t) * t * t * self._cy2 + \
|
|
t * t * t * 1.0
|
|
|
|
def toString(self) -> str:
|
|
return f"PathInterpolator({self._cx1}, {self._cy1}, {self._cx2}, {self._cy2})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# AnimationScale
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class AnimationScale(Stub):
|
|
"""AnimationScale — 动画缩放比例"""
|
|
|
|
def __init__(self, scale: float = 1.0):
|
|
super().__init__()
|
|
self._scale = scale
|
|
|
|
def getScale(self) -> float:
|
|
return self._scale
|
|
|
|
def setScale(self, scale: float):
|
|
self._scale = max(0.0, scale)
|
|
|
|
def toString(self) -> str:
|
|
return f"AnimationScale(scale={self._scale})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# AnimationSet
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class AnimationSet(Stub):
|
|
"""AnimationSet — 动画集合"""
|
|
|
|
def __init__(self, shareInterpolator: bool = True):
|
|
super().__init__()
|
|
self._share_interpolator = shareInterpolator
|
|
self._animations: List[Any] = []
|
|
self._interpolator: Optional[AnimationInterpolator] = None
|
|
self._duration: int = 0
|
|
self._fill_after = False
|
|
self._fill_before = False
|
|
self._repeat_count = 0
|
|
self._repeat_mode = RESTART
|
|
self._start_offset = 0
|
|
self._start_time = -1
|
|
|
|
def addAnimation(self, animation: Any):
|
|
self._animations.append(animation)
|
|
|
|
def getAnimations(self) -> List[Any]:
|
|
return list(self._animations)
|
|
|
|
def setDuration(self, duration: int):
|
|
self._duration = duration
|
|
for anim in self._animations:
|
|
if hasattr(anim, 'setDuration'):
|
|
anim.setDuration(duration)
|
|
|
|
def getDuration(self) -> int:
|
|
return self._duration
|
|
|
|
def setInterpolator(self, interpolator: AnimationInterpolator):
|
|
self._interpolator = interpolator
|
|
if self._share_interpolator:
|
|
for anim in self._animations:
|
|
if hasattr(anim, 'setInterpolator'):
|
|
anim.setInterpolator(interpolator)
|
|
|
|
def getInterpolator(self) -> Optional[AnimationInterpolator]:
|
|
return self._interpolator
|
|
|
|
def setFillAfter(self, fill: bool):
|
|
self._fill_after = fill
|
|
|
|
def isFillAfter(self) -> bool:
|
|
return self._fill_after
|
|
|
|
def setFillBefore(self, fill: bool):
|
|
self._fill_before = fill
|
|
|
|
def isFillBefore(self) -> bool:
|
|
return self._fill_before
|
|
|
|
def setRepeatCount(self, count: int):
|
|
self._repeat_count = count
|
|
|
|
def getRepeatCount(self) -> int:
|
|
return self._repeat_count
|
|
|
|
def setRepeatMode(self, mode: int):
|
|
self._repeat_mode = mode
|
|
|
|
def getRepeatMode(self) -> int:
|
|
return self._repeat_mode
|
|
|
|
def setStartOffset(self, offset: int):
|
|
self._start_offset = offset
|
|
|
|
def getStartOffset(self) -> int:
|
|
return self._start_offset
|
|
|
|
def start(self):
|
|
self._start_time = int(time.time() * 1000)
|
|
|
|
def cancel(self):
|
|
self._start_time = -1
|
|
|
|
def isRunning(self) -> bool:
|
|
return self._start_time >= 0
|
|
|
|
def hasStarted(self) -> bool:
|
|
return self._start_time >= 0
|
|
|
|
def toString(self) -> str:
|
|
return f"AnimationSet(animations={len(self._animations)}, duration={self._duration})"
|
|
|
|
def equals(self, other: Any) -> bool:
|
|
return self is other
|
|
|
|
def hashCode(self) -> int:
|
|
return id(self) & 0x7FFFFFFF
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# AnimationDescription
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class AnimationDescription(Stub):
|
|
"""AnimationDescription — 动画描述"""
|
|
|
|
def __init__(self, name: str = "", duration: int = 300,
|
|
interpolator: Optional[AnimationInterpolator] = None,
|
|
fillAfter: bool = False, repeatCount: int = 0):
|
|
super().__init__()
|
|
self._name = name
|
|
self._duration = duration
|
|
self._interpolator = interpolator or LinearInterpolator()
|
|
self._fill_after = fillAfter
|
|
self._repeat_count = repeatCount
|
|
|
|
def getName(self) -> str:
|
|
return self._name
|
|
|
|
def getDuration(self) -> int:
|
|
return self._duration
|
|
|
|
def getInterpolator(self) -> AnimationInterpolator:
|
|
return self._interpolator
|
|
|
|
def isFillAfter(self) -> bool:
|
|
return self._fill_after
|
|
|
|
def getRepeatCount(self) -> int:
|
|
return self._repeat_count
|
|
|
|
def toString(self) -> str:
|
|
return f"AnimationDescription(name={self._name}, duration={self._duration})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# RotateAnimation
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class RotateAnimation(Stub):
|
|
"""RotateAnimation — 旋转动画"""
|
|
|
|
def __init__(self, fromDegrees: float = 0.0, toDegrees: float = 360.0,
|
|
pivotX: float = 0.0, pivotY: float = 0.0,
|
|
pivotXType: int = RELATIVE_TO_SELF,
|
|
pivotYType: int = RELATIVE_TO_SELF):
|
|
super().__init__()
|
|
self._from_degrees = fromDegrees
|
|
self._to_degrees = toDegrees
|
|
self._pivot_x = pivotX
|
|
self._pivot_y = pivotY
|
|
self._pivot_x_type = pivotXType
|
|
self._pivot_y_type = pivotYType
|
|
self._duration = 300
|
|
self._interpolator: Optional[AnimationInterpolator] = None
|
|
self._repeat_count = 0
|
|
self._repeat_mode = RESTART
|
|
self._fill_after = False
|
|
self._fill_before = False
|
|
self._start_offset = 0
|
|
self._start_time = -1
|
|
|
|
def getFromDegrees(self) -> float:
|
|
return self._from_degrees
|
|
|
|
def getToDegrees(self) -> float:
|
|
return self._to_degrees
|
|
|
|
def getPivotX(self) -> float:
|
|
return self._pivot_x
|
|
|
|
def getPivotY(self) -> float:
|
|
return self._pivot_y
|
|
|
|
def getPivotXType(self) -> int:
|
|
return self._pivot_x_type
|
|
|
|
def getPivotYType(self) -> int:
|
|
return self._pivot_y_type
|
|
|
|
def setDuration(self, duration: int):
|
|
self._duration = duration
|
|
|
|
def getDuration(self) -> int:
|
|
return self._duration
|
|
|
|
def setInterpolator(self, interpolator: AnimationInterpolator):
|
|
self._interpolator = interpolator
|
|
|
|
def getInterpolator(self) -> Optional[AnimationInterpolator]:
|
|
return self._interpolator
|
|
|
|
def setRepeatCount(self, count: int):
|
|
self._repeat_count = count
|
|
|
|
def getRepeatCount(self) -> int:
|
|
return self._repeat_count
|
|
|
|
def setRepeatMode(self, mode: int):
|
|
self._repeat_mode = mode
|
|
|
|
def getRepeatMode(self) -> int:
|
|
return self._repeat_mode
|
|
|
|
def setFillAfter(self, fill: bool):
|
|
self._fill_after = fill
|
|
|
|
def isFillAfter(self) -> bool:
|
|
return self._fill_after
|
|
|
|
def setFillBefore(self, fill: bool):
|
|
self._fill_before = fill
|
|
|
|
def isFillBefore(self) -> bool:
|
|
return self._fill_before
|
|
|
|
def setStartOffset(self, offset: int):
|
|
self._start_offset = offset
|
|
|
|
def start(self):
|
|
self._start_time = int(time.time() * 1000)
|
|
|
|
def cancel(self):
|
|
self._start_time = -1
|
|
|
|
def toString(self) -> str:
|
|
return (f"RotateAnimation(from={self._from_degrees}, to={self._to_degrees}, "
|
|
f"duration={self._duration})")
|
|
|
|
def equals(self, other: Any) -> bool:
|
|
return self is other
|
|
|
|
def hashCode(self) -> int:
|
|
return id(self) & 0x7FFFFFFF
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# ScaleAnimation
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class ScaleAnimation(Stub):
|
|
"""ScaleAnimation — 缩放动画"""
|
|
|
|
def __init__(self, fromX: float = 0.0, toX: float = 1.0,
|
|
fromY: float = 0.0, toY: float = 1.0,
|
|
pivotX: float = 0.0, pivotY: float = 0.0,
|
|
pivotXType: int = RELATIVE_TO_SELF,
|
|
pivotYType: int = RELATIVE_TO_SELF):
|
|
super().__init__()
|
|
self._from_x = fromX
|
|
self._to_x = toX
|
|
self._from_y = fromY
|
|
self._to_y = toY
|
|
self._pivot_x = pivotX
|
|
self._pivot_y = pivotY
|
|
self._pivot_x_type = pivotXType
|
|
self._pivot_y_type = pivotYType
|
|
self._duration = 300
|
|
self._interpolator: Optional[AnimationInterpolator] = None
|
|
self._repeat_count = 0
|
|
self._fill_after = False
|
|
self._start_time = -1
|
|
|
|
def getFromX(self) -> float:
|
|
return self._from_x
|
|
|
|
def getToX(self) -> float:
|
|
return self._to_x
|
|
|
|
def getFromY(self) -> float:
|
|
return self._from_y
|
|
|
|
def getToY(self) -> float:
|
|
return self._to_y
|
|
|
|
def getPivotX(self) -> float:
|
|
return self._pivot_x
|
|
|
|
def getPivotY(self) -> float:
|
|
return self._pivot_y
|
|
|
|
def setDuration(self, duration: int):
|
|
self._duration = duration
|
|
|
|
def getDuration(self) -> int:
|
|
return self._duration
|
|
|
|
def setInterpolator(self, interpolator: AnimationInterpolator):
|
|
self._interpolator = interpolator
|
|
|
|
def getInterpolator(self) -> Optional[AnimationInterpolator]:
|
|
return self._interpolator
|
|
|
|
def setRepeatCount(self, count: int):
|
|
self._repeat_count = count
|
|
|
|
def setFillAfter(self, fill: bool):
|
|
self._fill_after = fill
|
|
|
|
def start(self):
|
|
self._start_time = int(time.time() * 1000)
|
|
|
|
def cancel(self):
|
|
self._start_time = -1
|
|
|
|
def toString(self) -> str:
|
|
return (f"ScaleAnimation(x={self._from_x}->{self._to_x}, "
|
|
f"y={self._from_y}->{self._to_y})")
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# TranslateAnimation (扩展)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class TranslateAnimation(Stub):
|
|
"""TranslateAnimation — 位移动画 (完整版)"""
|
|
|
|
def __init__(self, fromX: float = 0.0, toX: float = 0.0,
|
|
fromY: float = 0.0, toY: float = 0.0,
|
|
fromXType: int = RELATIVE_TO_SELF,
|
|
toXType: int = RELATIVE_TO_SELF,
|
|
fromYType: int = RELATIVE_TO_SELF,
|
|
toYType: int = RELATIVE_TO_SELF):
|
|
super().__init__()
|
|
self._from_x = fromX
|
|
self._to_x = toX
|
|
self._from_y = fromY
|
|
self._to_y = toY
|
|
self._from_x_type = fromXType
|
|
self._to_x_type = toXType
|
|
self._from_y_type = fromYType
|
|
self._to_y_type = toYType
|
|
self._duration = 300
|
|
self._interpolator: Optional[AnimationInterpolator] = None
|
|
self._repeat_count = 0
|
|
self._fill_after = False
|
|
self._start_time = -1
|
|
|
|
def getFromX(self) -> float:
|
|
return self._from_x
|
|
|
|
def getToX(self) -> float:
|
|
return self._to_x
|
|
|
|
def getFromY(self) -> float:
|
|
return self._from_y
|
|
|
|
def getToY(self) -> float:
|
|
return self._to_y
|
|
|
|
def setDuration(self, duration: int):
|
|
self._duration = duration
|
|
|
|
def getDuration(self) -> int:
|
|
return self._duration
|
|
|
|
def setInterpolator(self, interpolator: AnimationInterpolator):
|
|
self._interpolator = interpolator
|
|
|
|
def setRepeatCount(self, count: int):
|
|
self._repeat_count = count
|
|
|
|
def setFillAfter(self, fill: bool):
|
|
self._fill_after = fill
|
|
|
|
def start(self):
|
|
self._start_time = int(time.time() * 1000)
|
|
|
|
def cancel(self):
|
|
self._start_time = -1
|
|
|
|
def hasStarted(self) -> bool:
|
|
return self._start_time >= 0
|
|
|
|
def toString(self) -> str:
|
|
return (f"TranslateAnimation(x={self._from_x}->{self._to_x}, "
|
|
f"y={self._from_y}->{self._to_y})")
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# AlphaAnimation (扩展)
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class AlphaAnimation(Stub):
|
|
"""AlphaAnimation — 透明度动画 (完整版)"""
|
|
|
|
def __init__(self, fromAlpha: float = 0.0, toAlpha: float = 1.0):
|
|
super().__init__()
|
|
self._from_alpha = fromAlpha
|
|
self._to_alpha = toAlpha
|
|
self._duration = 300
|
|
self._interpolator: Optional[AnimationInterpolator] = None
|
|
self._repeat_count = 0
|
|
self._fill_after = False
|
|
self._start_time = -1
|
|
|
|
def getFromAlpha(self) -> float:
|
|
return self._from_alpha
|
|
|
|
def getToAlpha(self) -> float:
|
|
return self._to_alpha
|
|
|
|
def setDuration(self, duration: int):
|
|
self._duration = duration
|
|
|
|
def getDuration(self) -> int:
|
|
return self._duration
|
|
|
|
def setInterpolator(self, interpolator: AnimationInterpolator):
|
|
self._interpolator = interpolator
|
|
|
|
def getInterpolator(self) -> Optional[AnimationInterpolator]:
|
|
return self._interpolator
|
|
|
|
def setRepeatCount(self, count: int):
|
|
self._repeat_count = count
|
|
|
|
def setFillAfter(self, fill: bool):
|
|
self._fill_after = fill
|
|
|
|
def start(self):
|
|
self._start_time = int(time.time() * 1000)
|
|
|
|
def cancel(self):
|
|
self._start_time = -1
|
|
|
|
def hasStarted(self) -> bool:
|
|
return self._start_time >= 0
|
|
|
|
def toString(self) -> str:
|
|
return f"AlphaAnimation(from={self._from_alpha}, to={self._to_alpha})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# LayoutAnimationController
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class LayoutAnimationController(Stub):
|
|
"""LayoutAnimationController — 布局动画控制器"""
|
|
|
|
ORDER_NORMAL = 0
|
|
ORDER_REVERSE = 1
|
|
ORDER_RANDOM = 2
|
|
|
|
def __init__(self, animation: Optional[AnimationDescription] = None,
|
|
delay: float = 0.5, order: int = ORDER_NORMAL):
|
|
super().__init__()
|
|
self._animation = animation
|
|
self._delay = delay
|
|
self._order = order
|
|
self._interpolator: Optional[AnimationInterpolator] = None
|
|
|
|
def getAnimation(self) -> Optional[AnimationDescription]:
|
|
return self._animation
|
|
|
|
def setAnimation(self, animation: AnimationDescription):
|
|
self._animation = animation
|
|
|
|
def getDelay(self) -> float:
|
|
return self._delay
|
|
|
|
def setDelay(self, delay: float):
|
|
self._delay = delay
|
|
|
|
def getOrder(self) -> int:
|
|
return self._order
|
|
|
|
def setOrder(self, order: int):
|
|
self._order = order
|
|
|
|
def setInterpolator(self, interpolator: AnimationInterpolator):
|
|
self._interpolator = interpolator
|
|
|
|
def getInterpolator(self) -> Optional[AnimationInterpolator]:
|
|
return self._interpolator
|
|
|
|
def isEnabled(self) -> bool:
|
|
return self._animation is not None
|
|
|
|
def toString(self) -> str:
|
|
return f"LayoutAnimationController(delay={self._delay})"
|
|
|
|
def equals(self, other: Any) -> bool:
|
|
return self is other
|
|
|
|
def hashCode(self) -> int:
|
|
return id(self) & 0x7FFFFFFF
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# GridLayoutAnimationController
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class GridLayoutAnimationController(LayoutAnimationController):
|
|
"""GridLayoutAnimationController — 网格布局动画控制器"""
|
|
|
|
DIRECTION_LEFT_TO_RIGHT = 0
|
|
DIRECTION_RIGHT_TO_LEFT = 1
|
|
DIRECTION_TOP_TO_BOTTOM = 2
|
|
DIRECTION_BOTTOM_TO_TOP = 3
|
|
|
|
DIRECTION_HORIZONTAL_MASK = 1
|
|
DIRECTION_VERTICAL_MASK = 2
|
|
|
|
PRIORITY_NONE = 0
|
|
PRIORITY_COLUMN = 1
|
|
PRIORITY_ROW = 2
|
|
|
|
def __init__(self, animation: Optional[AnimationDescription] = None,
|
|
columnDelay: float = 0.5, rowDelay: float = 0.5,
|
|
direction: int = DIRECTION_LEFT_TO_RIGHT,
|
|
directionPriority: int = PRIORITY_NONE):
|
|
super().__init__(animation=animation, delay=0.5)
|
|
self._column_delay = columnDelay
|
|
self._row_delay = rowDelay
|
|
self._direction = direction
|
|
self._direction_priority = directionPriority
|
|
|
|
def getColumnDelay(self) -> float:
|
|
return self._column_delay
|
|
|
|
def setColumnDelay(self, delay: float):
|
|
self._column_delay = delay
|
|
|
|
def getRowDelay(self) -> float:
|
|
return self._row_delay
|
|
|
|
def setRowDelay(self, delay: float):
|
|
self._row_delay = delay
|
|
|
|
def getDirection(self) -> int:
|
|
return self._direction
|
|
|
|
def setDirection(self, direction: int):
|
|
self._direction = direction
|
|
|
|
def getDirectionPriority(self) -> int:
|
|
return self._direction_priority
|
|
|
|
def setDirectionPriority(self, priority: int):
|
|
self._direction_priority = priority
|
|
|
|
def toString(self) -> str:
|
|
return f"GridLayoutAnimationController(colDelay={self._column_delay})"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# AnimationUtils
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
class AnimationUtils(Stub):
|
|
"""AnimationUtils — 动画工具类"""
|
|
|
|
@staticmethod
|
|
def currentAnimationTimeMillis() -> int:
|
|
return int(time.time() * 1000)
|
|
|
|
@staticmethod
|
|
def loadAnimation(context: Any, id: int) -> Optional[AnimationDescription]:
|
|
return None
|
|
|
|
@staticmethod
|
|
def loadInterpolator(context: Any, id: int) -> Optional[AnimationInterpolator]:
|
|
return None
|
|
|
|
@staticmethod
|
|
def makeInAnimation(context: Any, fromLeft: bool = True) -> TranslateAnimation:
|
|
x = -1.0 if fromLeft else 1.0
|
|
anim = TranslateAnimation(fromX=x, toX=0.0, fromXType=RELATIVE_TO_PARENT,
|
|
toXType=RELATIVE_TO_PARENT)
|
|
anim.setDuration(300)
|
|
anim.setInterpolator(DecelerateInterpolator())
|
|
return anim
|
|
|
|
@staticmethod
|
|
def makeOutAnimation(context: Any, toRight: bool = True) -> TranslateAnimation:
|
|
x = 1.0 if toRight else -1.0
|
|
anim = TranslateAnimation(fromX=0.0, toX=x, fromXType=RELATIVE_TO_PARENT,
|
|
toXType=RELATIVE_TO_PARENT)
|
|
anim.setDuration(300)
|
|
anim.setInterpolator(AccelerateInterpolator())
|
|
return anim
|
|
|
|
@staticmethod
|
|
def makeInChildBottomAnimation(context: Any) -> TranslateAnimation:
|
|
anim = TranslateAnimation(fromX=0.0, toX=0.0,
|
|
fromY=1.0, toY=0.0,
|
|
fromYType=RELATIVE_TO_PARENT,
|
|
toYType=RELATIVE_TO_PARENT)
|
|
anim.setDuration(300)
|
|
anim.setInterpolator(DecelerateInterpolator())
|
|
return anim
|
|
|
|
@staticmethod
|
|
def createScaleUpAnimation(context: Any) -> ScaleAnimation:
|
|
anim = ScaleAnimation(fromX=0.0, toX=1.0, fromY=0.0, toY=1.0,
|
|
pivotX=0.5, pivotY=0.5,
|
|
pivotXType=RELATIVE_TO_SELF,
|
|
pivotYType=RELATIVE_TO_SELF)
|
|
anim.setDuration(300)
|
|
anim.setInterpolator(AccelerateDecelerateInterpolator())
|
|
return anim
|
|
|
|
@staticmethod
|
|
def createShrinkDownAnimation(context: Any) -> ScaleAnimation:
|
|
anim = ScaleAnimation(fromX=1.0, toX=0.0, fromY=1.0, toY=0.0,
|
|
pivotX=0.5, pivotY=0.5,
|
|
pivotXType=RELATIVE_TO_SELF,
|
|
pivotYType=RELATIVE_TO_SELF)
|
|
anim.setDuration(300)
|
|
anim.setInterpolator(AccelerateDecelerateInterpolator())
|
|
return anim
|
|
|
|
@staticmethod
|
|
def createFadeInAnimation(context: Any) -> AlphaAnimation:
|
|
anim = AlphaAnimation(fromAlpha=0.0, toAlpha=1.0)
|
|
anim.setDuration(300)
|
|
return anim
|
|
|
|
@staticmethod
|
|
def createFadeOutAnimation(context: Any) -> AlphaAnimation:
|
|
anim = AlphaAnimation(fromAlpha=1.0, toAlpha=0.0)
|
|
anim.setDuration(300)
|
|
return anim
|
|
|
|
@staticmethod
|
|
def createRotateAnimation(context: Any, fromDeg: float = 0.0,
|
|
toDeg: float = 360.0) -> RotateAnimation:
|
|
anim = RotateAnimation(fromDegrees=fromDeg, toDegrees=toDeg,
|
|
pivotX=0.5, pivotY=0.5)
|
|
anim.setDuration(500)
|
|
return anim
|
|
|
|
def toString(self) -> str:
|
|
return "AnimationUtils" |