1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'package:flutter/rendering.dart';
6
7import 'basic.dart';
8import 'framework.dart';
9
10/// An interface for widgets that can return the size this widget would prefer
11/// if it were otherwise unconstrained.
12///
13/// There are a few cases, notably [AppBar] and [TabBar], where it would be
14/// undesirable for the widget to constrain its own size but where the widget
15/// needs to expose a preferred or "default" size. For example a primary
16/// [Scaffold] sets its app bar height to the app bar's preferred height
17/// plus the height of the system status bar.
18///
19/// Widgets that need to know the preferred size of their child can require
20/// that their child implement this interface by using this class rather
21/// than [Widget] as the type of their `child` property.
22///
23/// Use [PreferredSize] to give a preferred size to an arbitrary widget.
24abstract class PreferredSizeWidget implements Widget {
25 /// The size this widget would prefer if it were otherwise unconstrained.
26 ///
27 /// In many cases it's only necessary to define one preferred dimension.
28 /// For example the [Scaffold] only depends on its app bar's preferred
29 /// height. In that case implementations of this method can just return
30 /// `Size.fromHeight(myAppBarHeight)`.
31 Size get preferredSize;
32}
33
34/// A widget with a preferred size.
35///
36/// This widget does not impose any constraints on its child, and it doesn't
37/// affect the child's layout in any way. It just advertises a preferred size
38/// which can be used by the parent.
39///
40/// Parents like [Scaffold] use [PreferredSizeWidget] to require that their
41/// children implement that interface. To give a preferred size to an arbitrary
42/// widget so that it can be used in a `child` property of that type, this
43/// widget, [PreferredSize], can be used.
44///
45/// Widgets like [AppBar] implement a [PreferredSizeWidget], so that this
46/// [PreferredSize] widget is not necessary for them.
47///
48/// {@tool dartpad}
49/// This sample shows a custom widget, similar to an [AppBar], which uses a
50/// [PreferredSize] widget, with its height set to 80 logical pixels.
51/// Changing the [PreferredSize] can be used to change the height
52/// of the custom app bar.
53///
54/// ** See code in examples/api/lib/widgets/preferred_size/preferred_size.0.dart **
55/// {@end-tool}
56///
57/// See also:
58///
59/// * [AppBar.bottom] and [Scaffold.appBar], which require preferred size widgets.
60/// * [PreferredSizeWidget], the interface which this widget implements to expose
61/// its preferred size.
62/// * [AppBar] and [TabBar], which implement PreferredSizeWidget.
63class PreferredSize extends StatelessWidget implements PreferredSizeWidget {
64 /// Creates a widget that has a preferred size that the parent can query.
65 const PreferredSize({
66 super.key,
67 required this.preferredSize,
68 required this.child,
69 });
70
71 /// The widget below this widget in the tree.
72 ///
73 /// {@macro flutter.widgets.ProxyWidget.child}
74 final Widget child;
75
76 @override
77 final Size preferredSize;
78
79 @override
80 Widget build(BuildContext context) => child;
81}
82