mirror of
https://github.com/flutter/samples.git
synced 2025-11-10 14:58:34 +00:00
[Gallery] Preserve demo state, simplify demo width calculations on desktop (#287)
* Maintain state on mobile * Refactor section width code * Fix state resetting on desktop * Remove unused import * Remove unecessary GestureDetectorBehavior
This commit is contained in:
@@ -3,7 +3,6 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:io' show Platform;
|
import 'dart:io' show Platform;
|
||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -256,12 +255,14 @@ class _DemoPageState extends State<DemoPage> with TickerProviderStateMixin {
|
|||||||
appBar.preferredSize.height;
|
appBar.preferredSize.height;
|
||||||
final maxSectionHeight = isDesktop ? contentHeight : contentHeight - 64;
|
final maxSectionHeight = isDesktop ? contentHeight : contentHeight - 64;
|
||||||
final horizontalPadding = isDesktop ? mediaQuery.size.width * 0.12 : 0.0;
|
final horizontalPadding = isDesktop ? mediaQuery.size.width * 0.12 : 0.0;
|
||||||
|
final maxSectionWidth = 420.0;
|
||||||
|
|
||||||
Widget section;
|
Widget section;
|
||||||
switch (_state) {
|
switch (_state) {
|
||||||
case _DemoState.options:
|
case _DemoState.options:
|
||||||
section = _DemoSectionOptions(
|
section = _DemoSectionOptions(
|
||||||
maxHeight: maxSectionHeight,
|
maxHeight: maxSectionHeight,
|
||||||
|
maxWidth: maxSectionWidth,
|
||||||
configurations: widget.demo.configurations,
|
configurations: widget.demo.configurations,
|
||||||
configIndex: _configIndex,
|
configIndex: _configIndex,
|
||||||
onConfigChanged: (index) {
|
onConfigChanged: (index) {
|
||||||
@@ -277,6 +278,7 @@ class _DemoPageState extends State<DemoPage> with TickerProviderStateMixin {
|
|||||||
case _DemoState.info:
|
case _DemoState.info:
|
||||||
section = _DemoSectionInfo(
|
section = _DemoSectionInfo(
|
||||||
maxHeight: maxSectionHeight,
|
maxHeight: maxSectionHeight,
|
||||||
|
maxWidth: maxSectionWidth,
|
||||||
title: _currentConfig.title,
|
title: _currentConfig.title,
|
||||||
description: _currentConfig.description,
|
description: _currentConfig.description,
|
||||||
);
|
);
|
||||||
@@ -314,46 +316,15 @@ class _DemoPageState extends State<DemoPage> with TickerProviderStateMixin {
|
|||||||
buildRoute: _currentConfig.buildRoute,
|
buildRoute: _currentConfig.buildRoute,
|
||||||
);
|
);
|
||||||
if (isDesktop) {
|
if (isDesktop) {
|
||||||
// If the available width is not very wide, reduce the amount of space
|
final isFullScreen = _state == _DemoState.fullscreen;
|
||||||
// between the demo content and the selected section.
|
final Widget sectionAndDemo = Row(
|
||||||
const reducedMiddleSpaceWidth = 48.0;
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
// Width of the space between the section and the demo content
|
if (!isFullScreen) Expanded(child: section),
|
||||||
// when the code is NOT displayed.
|
SizedBox(width: !isFullScreen ? 48.0 : 0),
|
||||||
final nonCodePageMiddleSpaceWidth = mediaQuery.size.width > 900
|
Expanded(child: demoContent),
|
||||||
? horizontalPadding
|
],
|
||||||
: reducedMiddleSpaceWidth;
|
);
|
||||||
|
|
||||||
// Width of the space between the section and the demo content
|
|
||||||
// when the code is displayed.
|
|
||||||
final codePageMiddleSpaceWidth =
|
|
||||||
min(reducedMiddleSpaceWidth, nonCodePageMiddleSpaceWidth);
|
|
||||||
|
|
||||||
// Width of the space between the section and the demo content
|
|
||||||
final middleSpaceWidth = _state == _DemoState.code
|
|
||||||
? codePageMiddleSpaceWidth
|
|
||||||
: nonCodePageMiddleSpaceWidth;
|
|
||||||
|
|
||||||
// Width for demo content.
|
|
||||||
// It is calculated in this way because the code demands more space.
|
|
||||||
final demoContentWidth = (mediaQuery.size.width -
|
|
||||||
horizontalPadding * 2 -
|
|
||||||
nonCodePageMiddleSpaceWidth) /
|
|
||||||
2;
|
|
||||||
|
|
||||||
final Widget sectionAndDemo = (_state == _DemoState.fullscreen)
|
|
||||||
? demoContent
|
|
||||||
: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Expanded(child: section),
|
|
||||||
SizedBox(width: middleSpaceWidth),
|
|
||||||
Container(
|
|
||||||
width: demoContentWidth,
|
|
||||||
child: demoContent,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
body = SafeArea(
|
body = SafeArea(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@@ -371,20 +342,22 @@ class _DemoPageState extends State<DemoPage> with TickerProviderStateMixin {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Add a tap gesture to collapse the currently opened section.
|
// Add a tap gesture to collapse the currently opened section.
|
||||||
if (_state != _DemoState.normal) {
|
demoContent = Semantics(
|
||||||
demoContent = Semantics(
|
label: MaterialLocalizations.of(context).modalBarrierDismissLabel,
|
||||||
label: MaterialLocalizations.of(context).modalBarrierDismissLabel,
|
child: GestureDetector(
|
||||||
child: GestureDetector(
|
onTap: () {
|
||||||
behavior: HitTestBehavior.opaque,
|
if (_state != _DemoState.normal) {
|
||||||
onTap: () {
|
|
||||||
setStateAndUpdate(() {
|
setStateAndUpdate(() {
|
||||||
_state = _DemoState.normal;
|
_state = _DemoState.normal;
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
child: ExcludeSemantics(child: demoContent),
|
},
|
||||||
|
child: Semantics(
|
||||||
|
excludeSemantics: _state != _DemoState.normal,
|
||||||
|
child: demoContent,
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
}
|
);
|
||||||
|
|
||||||
body = SafeArea(
|
body = SafeArea(
|
||||||
bottom: false,
|
bottom: false,
|
||||||
@@ -491,12 +464,14 @@ class _DemoSectionOptions extends StatelessWidget {
|
|||||||
const _DemoSectionOptions({
|
const _DemoSectionOptions({
|
||||||
Key key,
|
Key key,
|
||||||
this.maxHeight,
|
this.maxHeight,
|
||||||
|
this.maxWidth,
|
||||||
this.configurations,
|
this.configurations,
|
||||||
this.configIndex,
|
this.configIndex,
|
||||||
this.onConfigChanged,
|
this.onConfigChanged,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final double maxHeight;
|
final double maxHeight;
|
||||||
|
final double maxWidth;
|
||||||
final List<GalleryDemoConfiguration> configurations;
|
final List<GalleryDemoConfiguration> configurations;
|
||||||
final int configIndex;
|
final int configIndex;
|
||||||
final ValueChanged<int> onConfigChanged;
|
final ValueChanged<int> onConfigChanged;
|
||||||
@@ -506,49 +481,52 @@ class _DemoSectionOptions extends StatelessWidget {
|
|||||||
final textTheme = Theme.of(context).textTheme;
|
final textTheme = Theme.of(context).textTheme;
|
||||||
final colorScheme = Theme.of(context).colorScheme;
|
final colorScheme = Theme.of(context).colorScheme;
|
||||||
|
|
||||||
return Container(
|
return Align(
|
||||||
constraints: BoxConstraints(maxHeight: maxHeight),
|
alignment: AlignmentDirectional.topStart,
|
||||||
child: Column(
|
child: Container(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
constraints: BoxConstraints(maxHeight: maxHeight, maxWidth: maxWidth),
|
||||||
mainAxisSize: MainAxisSize.min,
|
child: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Padding(
|
mainAxisSize: MainAxisSize.min,
|
||||||
padding: const EdgeInsetsDirectional.only(
|
children: [
|
||||||
start: 24,
|
Padding(
|
||||||
top: 12,
|
padding: const EdgeInsetsDirectional.only(
|
||||||
end: 24,
|
start: 24,
|
||||||
),
|
top: 12,
|
||||||
child: Text(
|
end: 24,
|
||||||
GalleryLocalizations.of(context).demoOptionsTooltip,
|
),
|
||||||
style: textTheme.display1.apply(
|
child: Text(
|
||||||
color: colorScheme.onSurface,
|
GalleryLocalizations.of(context).demoOptionsTooltip,
|
||||||
fontSizeDelta:
|
style: textTheme.display1.apply(
|
||||||
isDisplayDesktop(context) ? desktopDisplay1FontDelta : 0,
|
color: colorScheme.onSurface,
|
||||||
|
fontSizeDelta:
|
||||||
|
isDisplayDesktop(context) ? desktopDisplay1FontDelta : 0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Divider(
|
||||||
Divider(
|
thickness: 1,
|
||||||
thickness: 1,
|
height: 16,
|
||||||
height: 16,
|
color: colorScheme.onSurface,
|
||||||
color: colorScheme.onSurface,
|
|
||||||
),
|
|
||||||
Flexible(
|
|
||||||
child: ListView(
|
|
||||||
shrinkWrap: true,
|
|
||||||
children: [
|
|
||||||
for (final configuration in configurations)
|
|
||||||
_DemoSectionOptionsItem(
|
|
||||||
title: configuration.title,
|
|
||||||
isSelected: configuration == configurations[configIndex],
|
|
||||||
onTap: () {
|
|
||||||
onConfigChanged(configurations.indexOf(configuration));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
Flexible(
|
||||||
SizedBox(height: 12),
|
child: ListView(
|
||||||
],
|
shrinkWrap: true,
|
||||||
|
children: [
|
||||||
|
for (final configuration in configurations)
|
||||||
|
_DemoSectionOptionsItem(
|
||||||
|
title: configuration.title,
|
||||||
|
isSelected: configuration == configurations[configIndex],
|
||||||
|
onTap: () {
|
||||||
|
onConfigChanged(configurations.indexOf(configuration));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 12),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -594,11 +572,13 @@ class _DemoSectionInfo extends StatelessWidget {
|
|||||||
const _DemoSectionInfo({
|
const _DemoSectionInfo({
|
||||||
Key key,
|
Key key,
|
||||||
this.maxHeight,
|
this.maxHeight,
|
||||||
|
this.maxWidth,
|
||||||
this.title,
|
this.title,
|
||||||
this.description,
|
this.description,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final double maxHeight;
|
final double maxHeight;
|
||||||
|
final double maxWidth;
|
||||||
final String title;
|
final String title;
|
||||||
final String description;
|
final String description;
|
||||||
|
|
||||||
@@ -607,33 +587,36 @@ class _DemoSectionInfo extends StatelessWidget {
|
|||||||
final textTheme = Theme.of(context).textTheme;
|
final textTheme = Theme.of(context).textTheme;
|
||||||
final colorScheme = Theme.of(context).colorScheme;
|
final colorScheme = Theme.of(context).colorScheme;
|
||||||
|
|
||||||
return Container(
|
return Align(
|
||||||
padding: const EdgeInsetsDirectional.only(
|
alignment: AlignmentDirectional.topStart,
|
||||||
start: 24,
|
child: Container(
|
||||||
top: 12,
|
padding: const EdgeInsetsDirectional.only(
|
||||||
end: 24,
|
start: 24,
|
||||||
bottom: 32,
|
top: 12,
|
||||||
),
|
end: 24,
|
||||||
constraints: BoxConstraints(maxHeight: maxHeight),
|
bottom: 32,
|
||||||
child: SingleChildScrollView(
|
),
|
||||||
child: Column(
|
constraints: BoxConstraints(maxHeight: maxHeight, maxWidth: maxWidth),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: SingleChildScrollView(
|
||||||
mainAxisSize: MainAxisSize.min,
|
child: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Text(
|
mainAxisSize: MainAxisSize.min,
|
||||||
title,
|
children: [
|
||||||
style: textTheme.display1.apply(
|
Text(
|
||||||
color: colorScheme.onSurface,
|
title,
|
||||||
fontSizeDelta:
|
style: textTheme.display1.apply(
|
||||||
isDisplayDesktop(context) ? desktopDisplay1FontDelta : 0,
|
color: colorScheme.onSurface,
|
||||||
|
fontSizeDelta:
|
||||||
|
isDisplayDesktop(context) ? desktopDisplay1FontDelta : 0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
SizedBox(height: 12),
|
||||||
SizedBox(height: 12),
|
Text(
|
||||||
Text(
|
description,
|
||||||
description,
|
style: textTheme.body1.apply(color: colorScheme.onSurface),
|
||||||
style: textTheme.body1.apply(color: colorScheme.onSurface),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user