Update timeline view to have a max width for the scrolling area

This commit is contained in:
Shawn 2022-10-27 10:26:43 -06:00
parent 048dae8ce8
commit 9a27803d67
2 changed files with 93 additions and 88 deletions

View File

@ -50,7 +50,7 @@ class _EventPopupsState extends State<_EventPopups> {
key: ValueKey(_eventToShow?.year),
child: IntrinsicHeight(
child: SizedBox(
width: 600,
width: $styles.sizes.maxContentWidth3,
child: Padding(
padding: EdgeInsets.all($styles.insets.md),
child: TimelineEventCard(

View File

@ -24,6 +24,7 @@ class _ScalingViewportState extends State<_ScrollingViewport> {
late final _ScrollingViewportController controller = _ScrollingViewportController(this);
static const double _minTimelineSize = 100;
final _currentEventMarker = ValueNotifier<TimelineEvent?>(null);
@override
void initState() {
super.initState();
@ -44,50 +45,41 @@ class _ScalingViewportState extends State<_ScrollingViewport> {
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (_, constraints) {
// cache constraints, so they can be used to maintain the selected year while zooming
controller._constraints = constraints;
double vtPadding = constraints.maxHeight / 2;
double size = controller.calculateContentHeight();
return GestureDetector(
// Handle pinch to zoom
onScaleUpdate: controller._handleScaleUpdate,
onScaleStart: controller._handleScaleStart,
behavior: HitTestBehavior.translucent,
// Fade in entire view when first shown
child: Animate(
effects: const [FadeEffect()],
child: Stack(
return GestureDetector(
// Handle pinch to zoom
onScaleUpdate: controller._handleScaleUpdate,
onScaleStart: controller._handleScaleStart,
behavior: HitTestBehavior.translucent,
// Fade in entire view when first shown
child: Stack(
children: [
Column(
children: [
Column(
children: [
/// Main scrolling area, holds the year markers, and the [WondersTimelineBuilder]
Expanded(
child: _buildScrollingArea(vtPadding, size, context, constraints),
),
Gap($styles.insets.xs),
/// Era Text (classical, modern etc)
_buildAnimatedEraText(context),
Gap($styles.insets.xs),
],
/// Main scrolling area, holds the year markers, and the [WondersTimelineBuilder]
Expanded(
child: _buildScrollingArea(context),
),
Gap($styles.insets.xs),
/// Dashed line with a year that changes as we scroll
IgnorePointer(
ignoringSemantics: false,
child: AnimatedBuilder(
animation: controller.scroller,
builder: (_, __) {
return _DashedDividerWithYear(controller.calculateYearFromScrollPos());
},
),
),
/// Era Text (classical, modern etc)
_buildAnimatedEraText(context),
Gap($styles.insets.xs),
],
).animate().fadeIn(),
/// Dashed line with a year that changes as we scroll
IgnorePointer(
ignoringSemantics: false,
child: AnimatedBuilder(
animation: controller.scroller,
builder: (_, __) {
return _DashedDividerWithYear(controller.calculateYearFromScrollPos());
},
),
),
),
);
});
],
),
);
}
AnimatedBuilder _buildAnimatedEraText(BuildContext context) {
@ -107,7 +99,7 @@ class _ScalingViewportState extends State<_ScrollingViewport> {
});
}
Widget _buildScrollingArea(double vtPadding, double size, BuildContext context, BoxConstraints constraints) {
Widget _buildScrollingArea(BuildContext context) {
// Builds a TimelineSection, and passes it the currently selected yr based on scroll position.
// Rebuilds when timeline is scrolled.
Widget buildTimelineSection(WonderData data) {
@ -124,59 +116,72 @@ class _ScalingViewportState extends State<_ScrollingViewport> {
);
}
return Stack(
children: [
SingleChildScrollView(
controller: controller.scroller,
padding: EdgeInsets.symmetric(vertical: vtPadding),
// A stack inside a SizedBox which sets its overall height
child: SizedBox(
height: size,
width: double.infinity,
child: Stack(
children: [
/// Year Markers
_YearMarkers(),
return LayoutBuilder(
builder: (_, constraints) {
// cache constraints, so they can be used to maintain the selected year while zooming
controller._constraints = constraints;
double vtPadding = constraints.maxHeight / 2;
double size = controller.calculateContentHeight();
final contentSize = min($styles.sizes.maxContentWidth2, constraints.maxWidth);
return Stack(
children: [
SingleChildScrollView(
controller: controller.scroller,
padding: EdgeInsets.symmetric(vertical: vtPadding),
// A stack inside a SizedBox which sets its overall height
child: Center(
child: SizedBox(
height: size,
width: contentSize,
child: Stack(
children: [
/// Year Markers
_YearMarkers(),
/// individual timeline sections
Positioned.fill(
left: 100,
right: $styles.insets.sm,
child: FocusTraversalGroup(
child: WondersTimelineBuilder(
axis: Axis.vertical,
crossAxisGap: max(6, (constraints.maxWidth - (120 * 3)) / 2),
minSize: _minTimelineSize,
timelineBuilder: (_, data, __) => buildTimelineSection(data)),
/// individual timeline sections
Positioned.fill(
left: 100,
right: $styles.insets.sm,
child: FocusTraversalGroup(
//child: Placeholder(),
child: WondersTimelineBuilder(
axis: Axis.vertical,
crossAxisGap: max(6, (contentSize - (120 * 3)) / 2),
minSize: _minTimelineSize,
timelineBuilder: (_, data, __) => buildTimelineSection(data),
),
),
),
/// Event Markers, rebuilds on scroll
AnimatedBuilder(
animation: controller.scroller,
builder: (_, __) => _EventMarkers(
controller.calculateYearFromScrollPos(),
onEventChanged: _handleEventMarkerChanged,
),
),
],
),
),
/// Event Markers, rebuilds on scroll
AnimatedBuilder(
animation: controller.scroller,
builder: (_, __) => _EventMarkers(
controller.calculateYearFromScrollPos(),
onEventChanged: _handleEventMarkerChanged,
),
),
],
),
),
),
),
/// Top and bottom gradients for visual style
ListOverscollGradient(),
BottomCenter(
child: ListOverscollGradient(bottomUp: true),
),
/// Top and bottom gradients for visual style
ListOverscollGradient(),
BottomCenter(
child: ListOverscollGradient(bottomUp: true),
),
/// Event Popups, rebuilds when [_currentEventMarker] changes
ValueListenableBuilder<TimelineEvent?>(
valueListenable: _currentEventMarker,
builder: (_, data, __) {
return _EventPopups(currentEvent: data);
})
],
/// Event Popups, rebuilds when [_currentEventMarker] changes
ValueListenableBuilder<TimelineEvent?>(
valueListenable: _currentEventMarker,
builder: (_, data, __) {
return _EventPopups(currentEvent: data);
})
],
);
},
);
}
}