mirror of
https://github.com/flutter/samples.git
synced 2025-11-08 13:58:47 +00:00
126 lines
4.0 KiB
Dart
126 lines
4.0 KiB
Dart
// Copyright 2022, the Flutter project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
/// A widget that makes it easy to create a screen with a square-ish
|
|
/// main area, a smaller menu area, and a small area for a message on top.
|
|
/// It works in both orientations on mobile- and tablet-sized screens.
|
|
class ResponsiveScreen extends StatelessWidget {
|
|
/// This is the "hero" of the screen. It's more or less square, and will
|
|
/// be placed in the visual "center" of the screen.
|
|
final Widget squarishMainArea;
|
|
|
|
/// The second-largest area after [squarishMainArea]. It can be narrow
|
|
/// or wide.
|
|
final Widget rectangularMenuArea;
|
|
|
|
/// An area reserved for some static text close to the top of the screen.
|
|
final Widget topMessageArea;
|
|
|
|
/// How much bigger should the [squarishMainArea] be compared to the other
|
|
/// elements.
|
|
final double mainAreaProminence;
|
|
|
|
const ResponsiveScreen({
|
|
required this.squarishMainArea,
|
|
required this.rectangularMenuArea,
|
|
this.topMessageArea = const SizedBox.shrink(),
|
|
this.mainAreaProminence = 0.8,
|
|
super.key,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return LayoutBuilder(
|
|
builder: (context, constraints) {
|
|
// This widget wants to fill the whole screen.
|
|
final size = constraints.biggest;
|
|
final padding = EdgeInsets.all(size.shortestSide / 30);
|
|
|
|
if (size.height >= size.width) {
|
|
// "Portrait" / "mobile" mode.
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
SafeArea(
|
|
bottom: false,
|
|
child: Padding(
|
|
padding: padding,
|
|
child: topMessageArea,
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: (mainAreaProminence * 100).round(),
|
|
child: SafeArea(
|
|
top: false,
|
|
bottom: false,
|
|
minimum: padding,
|
|
child: squarishMainArea,
|
|
),
|
|
),
|
|
SafeArea(
|
|
top: false,
|
|
maintainBottomViewPadding: true,
|
|
child: Padding(
|
|
padding: padding,
|
|
child: rectangularMenuArea,
|
|
),
|
|
),
|
|
],
|
|
);
|
|
} else {
|
|
// "Landscape" / "tablet" mode.
|
|
final isLarge = size.width > 900;
|
|
|
|
return Row(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
Expanded(
|
|
flex: isLarge ? 7 : 5,
|
|
child: SafeArea(
|
|
right: false,
|
|
maintainBottomViewPadding: true,
|
|
minimum: padding,
|
|
child: squarishMainArea,
|
|
),
|
|
),
|
|
Expanded(
|
|
flex: 3,
|
|
child: Column(
|
|
children: [
|
|
SafeArea(
|
|
bottom: false,
|
|
left: false,
|
|
maintainBottomViewPadding: true,
|
|
child: Padding(
|
|
padding: padding,
|
|
child: topMessageArea,
|
|
),
|
|
),
|
|
Expanded(
|
|
child: SafeArea(
|
|
top: false,
|
|
left: false,
|
|
maintainBottomViewPadding: true,
|
|
child: Align(
|
|
alignment: Alignment.bottomCenter,
|
|
child: Padding(
|
|
padding: padding,
|
|
child: rectangularMenuArea,
|
|
),
|
|
),
|
|
),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
},
|
|
);
|
|
}
|
|
}
|