preferred_size.dart 4.73 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/rendering.dart';

import 'basic.dart';
import 'framework.dart';

/// An interface for widgets that can return the size this widget would prefer
/// if it were otherwise unconstrained.
///
/// There are a few cases, notably [AppBar] and [TabBar], where it would be
/// undesirable for the widget to constrain its own size but where the widget
/// needs to expose a preferred or "default" size. For example a primary
/// [Scaffold] sets its app bar height to the app bar's preferred height
/// plus the height of the system status bar.
///
19 20 21 22
/// Widgets that need to know the preferred size of their child can require
/// that their child implement this interface by using this class rather
/// than [Widget] as the type of their `child` property.
///
23 24 25 26 27 28 29
/// Use [PreferredSize] to give a preferred size to an arbitrary widget.
abstract class PreferredSizeWidget implements Widget {
  /// The size this widget would prefer if it were otherwise unconstrained.
  ///
  /// In many cases it's only necessary to define one preferred dimension.
  /// For example the [Scaffold] only depends on its app bar's preferred
  /// height. In that case implementations of this method can just return
30
  /// `new Size.fromHeight(myAppBarHeight)`.
31 32 33
  Size get preferredSize;
}

34
/// A widget with a preferred size.
35
///
36 37 38
/// This widget does not impose any constraints on its child, and it doesn't
/// affect the child's layout in any way. It just advertises a preferred size
/// which can be used by the parent.
39
///
40 41 42 43 44 45 46
/// Parents like [Scaffold] use [PreferredSizeWidget] to require that their
/// children implement that interface. To give a preferred size to an arbitrary
/// widget so that it can be used in a `child` property of that type, this
/// widget, [PreferredSize], can be used.
///
/// Widgets like [AppBar] implement a [PreferredSizeWidget], so that this
/// [PreferredSize] widget is not necessary for them.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
///
/// {@tool dartpad --template=stateless_widget_material}
///
/// This sample shows a custom widget, similar to an [AppBar], which uses a
/// [PreferredSize] widget, with its height set to 80 logical pixels.
/// Changing the [PreferredSize] can be used to change the height
/// of the custom app bar.
///
/// ```dart preamble
/// class AppBarContent extends StatelessWidget {
///   @override
///   Widget build(BuildContext context) {
///     return Column(
///       mainAxisAlignment: MainAxisAlignment.end,
///       children: [
///         Padding(
///           padding: const EdgeInsets.symmetric(horizontal: 10),
///           child: Row(
///             children: [
///               Text(
///                 "PreferredSize Sample",
///                 style: TextStyle(color: Colors.white),
///               ),
///               Spacer(),
///               IconButton(
///                 icon: Icon(
///                   Icons.search,
///                   size: 20,
///                 ),
///                 color: Colors.white,
///                 onPressed: () {},
///               ),
///               IconButton(
///                 icon: Icon(
///                   Icons.more_vert,
///                   size: 20,
///                 ),
///                 color: Colors.white,
///                 onPressed: () {},
///               ),
///             ],
///           ),
///         ),
///       ],
///     );
///   }
/// }
/// ```
///```dart
/// Widget build(BuildContext context) {
///   return Scaffold(
///     appBar: PreferredSize(
///       preferredSize: const Size.fromHeight(80.0),
///       child: Container(
///         decoration: BoxDecoration(
///           gradient: LinearGradient(
///             colors: [Colors.blue, Colors.pink],
///           ),
///         ),
///         child: AppBarContent(),
///       ),
///     ),
///     body: Center(
///       child: Text("Content"),
///     ),
///   );
/// }
/// ```
/// {@end-tool}
///
117 118 119 120 121 122 123
/// See also:
///
///  * [AppBar.bottom] and [Scaffold.appBar], which require preferred size widgets.
///  * [PreferredSizeWidget], the interface which this widget implements to expose
///    its preferred size.
///  * [AppBar] and [TabBar], which implement PreferredSizeWidget.
class PreferredSize extends StatelessWidget implements PreferredSizeWidget {
124
  /// Creates a widget that has a preferred size that the parent can query.
125
  const PreferredSize({
126 127 128
    Key? key,
    required this.child,
    required this.preferredSize,
129 130
  }) : super(key: key);

131
  /// The widget below this widget in the tree.
132
  ///
133
  /// {@macro flutter.widgets.ProxyWidget.child}
134 135 136 137 138 139 140 141
  final Widget child;

  @override
  final Size preferredSize;

  @override
  Widget build(BuildContext context) => child;
}