Files
tongxunruanjian/mobile-next/openim_live/lib/src/widgets/call_page_host.dart
T
9bde926c81 fix(mobile-next): 按 B-91 收口 Android 通话视觉打回项
呼出/通话中按钮、计时器、底色、60s 未接与进出场动效对齐视觉规范。

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-08-20 09:58:28 +08:00

73 lines
1.7 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:openim_common/openim_common.dart';
/// 通话页进出:250ms 自下而上滑入 ease-out,不可打断。
class CallPageHost extends StatefulWidget {
const CallPageHost({
Key? key,
required this.child,
}) : super(key: key);
final Widget child;
@override
CallPageHostState createState() => CallPageHostState();
}
class CallPageHostState extends State<CallPageHost> with SingleTickerProviderStateMixin {
late final AnimationController _controller;
Completer<void>? _dismissing;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: Styles.callPageMotion,
);
_controller.forward();
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
_controller.duration = Styles.motionOf(context, Styles.callPageMotion);
}
Future<void> dismiss() {
if (_dismissing != null) return _dismissing!.future;
_dismissing = Completer<void>();
final future = _controller.status == AnimationStatus.dismissed
? Future<void>.value()
: _controller.reverse();
future.whenComplete(() {
if (_dismissing?.isCompleted == false) {
_dismissing!.complete();
}
});
return _dismissing!.future;
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, 1),
end: Offset.zero,
).animate(CurvedAnimation(parent: _controller, curve: Curves.easeOut)),
child: Material(
color: Styles.c_callBg,
child: widget.child,
),
);
}
}