fix(player): 持久化竖滑播放画面层
This commit is contained in:
1 parent
5dafc68775
commit
2a32dec183
5 files changed
+593
-101
No files matched your search
@@ -55,6 +55,19 @@ void main() {
|
||||
pageViews.where((pageView) => pageView.scrollDirection == Axis.vertical),
|
||||
hasLength(1),
|
||||
);
|
||||
expect(find.byKey(const Key('player-render-stack')), findsOneWidget);
|
||||
final renderStackPageAncestors = tester.widgetList<PageView>(
|
||||
find.ancestor(
|
||||
of: find.byKey(const Key('player-render-stack')),
|
||||
matching: find.byType(PageView),
|
||||
),
|
||||
);
|
||||
expect(
|
||||
renderStackPageAncestors.where(
|
||||
(pageView) => pageView.scrollDirection == Axis.vertical,
|
||||
),
|
||||
isEmpty,
|
||||
);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:fruitshorts/pages/player/widgets/player_render_stack.dart';
|
||||
import 'package:fruitshorts/pages/player/widgets/player_video_surface.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('should_keep_slots_alive_and_only_translate_during_page_change', (
|
||||
tester,
|
||||
) async {
|
||||
final pages = PageController(initialPage: 1);
|
||||
final previousController = _controller('previous');
|
||||
final currentController = _controller('current');
|
||||
final nextController = _controller('next');
|
||||
addTearDown(pages.dispose);
|
||||
addTearDown(previousController.dispose);
|
||||
addTearDown(currentController.dispose);
|
||||
addTearDown(nextController.dispose);
|
||||
|
||||
var currentIndex = 1;
|
||||
late StateSetter rebuild;
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
rebuild = setState;
|
||||
return Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
PlayerRenderStack(
|
||||
pageController: pages,
|
||||
slots: _slots(
|
||||
currentIndex: currentIndex,
|
||||
previousController: previousController,
|
||||
currentController: currentController,
|
||||
nextController: nextController,
|
||||
),
|
||||
),
|
||||
PageView(
|
||||
controller: pages,
|
||||
children: const [
|
||||
SizedBox.expand(key: Key('page-0')),
|
||||
SizedBox.expand(key: Key('page-1')),
|
||||
SizedBox.expand(key: Key('page-2')),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pump();
|
||||
|
||||
final currentSlot = find.byKey(
|
||||
const ValueKey('player-render-slot-current'),
|
||||
);
|
||||
final currentState = tester.state(currentSlot);
|
||||
final currentElement = tester.element(currentSlot);
|
||||
final currentSurface = tester.widget<PlayerVideoSurface>(currentSlot);
|
||||
expect(currentSurface.controller, same(currentController));
|
||||
expect(_translationY(tester, 'current'), 0);
|
||||
expect(_translationY(tester, 'next'), greaterThan(0));
|
||||
|
||||
pages.jumpToPage(2);
|
||||
await tester.pump();
|
||||
await tester.pump();
|
||||
|
||||
expect(tester.state(currentSlot), same(currentState));
|
||||
expect(tester.element(currentSlot), same(currentElement));
|
||||
expect(
|
||||
tester.widget<PlayerVideoSurface>(currentSlot).controller,
|
||||
same(currentController),
|
||||
);
|
||||
expect(_translationY(tester, 'current'), lessThan(0));
|
||||
expect(_translationY(tester, 'next'), 0);
|
||||
|
||||
rebuild(() => currentIndex = 2);
|
||||
await tester.pump();
|
||||
|
||||
expect(tester.state(currentSlot), same(currentState));
|
||||
expect(tester.element(currentSlot), same(currentElement));
|
||||
expect(_translationY(tester, 'current'), 0);
|
||||
expect(_translationY(tester, 'previous'), lessThan(0));
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byType(PlayerRenderStack),
|
||||
matching: find.byType(IgnorePointer),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Map<PlayerRenderSlotRole, PlayerRenderSlotData> _slots({
|
||||
required int currentIndex,
|
||||
required VideoPlayerController previousController,
|
||||
required VideoPlayerController currentController,
|
||||
required VideoPlayerController nextController,
|
||||
}) {
|
||||
return {
|
||||
PlayerRenderSlotRole.previous: PlayerRenderSlotData(
|
||||
role: PlayerRenderSlotRole.previous,
|
||||
index: currentIndex - 1,
|
||||
pagePosition: (currentIndex - 1).toDouble(),
|
||||
controller: previousController,
|
||||
placeholder: const ColoredBox(
|
||||
key: Key('previous-placeholder'),
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
PlayerRenderSlotRole.current: PlayerRenderSlotData(
|
||||
role: PlayerRenderSlotRole.current,
|
||||
index: currentIndex,
|
||||
pagePosition: currentIndex.toDouble(),
|
||||
controller: currentController,
|
||||
placeholder: const ColoredBox(
|
||||
key: Key('current-placeholder'),
|
||||
color: Colors.green,
|
||||
),
|
||||
),
|
||||
PlayerRenderSlotRole.next: PlayerRenderSlotData(
|
||||
role: PlayerRenderSlotRole.next,
|
||||
index: currentIndex + 1,
|
||||
pagePosition: (currentIndex + 1).toDouble(),
|
||||
controller: nextController,
|
||||
placeholder: const ColoredBox(
|
||||
key: Key('next-placeholder'),
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
VideoPlayerController _controller(String name) {
|
||||
return VideoPlayerController.networkUrl(
|
||||
Uri.parse('https://example.test/$name.mp4'),
|
||||
);
|
||||
}
|
||||
|
||||
double _translationY(WidgetTester tester, String role) {
|
||||
final transform = tester.widget<Transform>(
|
||||
find.byKey(Key('player-render-transform-$role')),
|
||||
);
|
||||
return transform.transform.getTranslation().y;
|
||||
}
|
||||
Reference in new issue
Block a user