Skip to content

Instantly share code, notes, and snippets.

@flutterdevrelgists
Created January 24, 2023 23:02
Show Gist options
  • Save flutterdevrelgists/8ddadf16f5600912ded9eddcde9ccbe8 to your computer and use it in GitHub Desktop.
Save flutterdevrelgists/8ddadf16f5600912ded9eddcde9ccbe8 to your computer and use it in GitHub Desktop.
Adaptive UI Talk LayoutBuilder Example
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/// Flutter code sample for [LayoutBuilder].
import 'package:flutter/material.dart';
void main() => runApp(const LayoutBuilderExample());
/// This displays a row of icon buttons, and if the row is too narrow to display
/// all of them, it moves any that don't fit into an overflow menu.
///
/// This widget is a [PreferredSizeWidget], so it can be used as a
/// [Scaffold.appBar].
class IconButtonBar extends StatefulWidget with PreferredSizeWidget {
const IconButtonBar({
super.key,
required this.childSize,
required this.children,
});
/// The fixed width for each of the children.
final Size childSize;
/// The list of widgets (typically [IconButton]s) to display.
///
/// They should each be able to be displayed at [childSize]. They will
/// automatically be placed inside of a [SizedBox] that is [childSize] in
/// size.
final List<Widget> children;
@override
Size get preferredSize => Size(childSize.width * children.length, childSize.height);
@override
State<IconButtonBar> createState() => _IconButtonBarState();
}
class _IconButtonBarState extends State<IconButtonBar> {
final GlobalKey buttonKey = GlobalKey();
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
int visibleChildren = constraints.constrain(widget.preferredSize).width ~/ widget.childSize.width;
visibleChildren = (visibleChildren < widget.children.length) ? visibleChildren - 1 : widget.children.length;
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
...widget.children.sublist(0, visibleChildren),
if (visibleChildren < widget.children.length)
OverflowMenu(key: buttonKey, children: widget.children.sublist(visibleChildren, widget.children.length)),
].map<Widget>((Widget child) => SizedBox.fromSize(size: widget.childSize, child: child)).toList(),
);
},
);
}
}
class OverflowMenu extends StatefulWidget {
const OverflowMenu({
super.key,
required this.children,
this.icon,
});
final List<Widget> children;
final Widget? icon;
@override
State<OverflowMenu> createState() => _OverflowMenuState();
}
class _OverflowMenuState extends State<OverflowMenu> {
final GlobalKey buttonKey = GlobalKey();
@override
Widget build(BuildContext context) {
return MenuAnchor(
style: const MenuStyle(alignment: AlignmentDirectional.bottomStart),
builder: (context, controller, child) {
return IconButton(
key: buttonKey,
icon: widget.icon ?? const Icon(Icons.more_vert),
onPressed: () {
if (controller.isOpen) {
controller.close();
} else {
controller.open();
}
},
);
},
menuChildren: widget.children,
);
}
}
class LayoutBuilderExample extends StatelessWidget {
const LayoutBuilderExample({ super.key });
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: IconButtonBar(
childSize: const Size(48, 48),
children: [
IconButton(onPressed: () {}, icon: const Icon(Icons.call)),
IconButton(onPressed: () {}, icon: const Icon(Icons.calendar_month)),
IconButton(onPressed: () {}, icon: const Icon(Icons.hotel)),
IconButton(onPressed: () {}, icon: const Icon(Icons.car_rental)),
IconButton(onPressed: () {}, icon: const Icon(Icons.airplanemode_on)),
IconButton(onPressed: () {}, icon: const Icon(Icons.train)),
IconButton(onPressed: () {}, icon: const Icon(Icons.rocket)),
IconButton(onPressed: () {}, icon: const Icon(Icons.alarm_add)),
IconButton(onPressed: () {}, icon: const Icon(Icons.alarm_off)),
],
),
body: const Center(
child: AspectRatio(
aspectRatio: 1.0,
child: FlutterLogo(),
),
),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment