media_query.dart 5.02 KB
Newer Older
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
import 'dart:ui' as ui;

7 8
import 'package:meta/meta.dart';

9 10 11
import 'basic.dart';
import 'framework.dart';

12 13 14 15
/// Whether in portrait or landscape.
enum Orientation {
  /// Taller than wide.
  portrait,
16

17 18 19
  /// Wider than tall.
  landscape
}
20

21 22 23 24 25 26 27 28
/// Information about a piece of media (e.g., a window).
///
/// For example, the [MediaQueryData.size] property contains the width and
/// height of the current window.
///
/// To obtain the current [MediaQueryData] for a given [BuildContext], use the
/// [MediaQuery.of] function. For example, to obtain the size of the current
/// window, use `MediaQuery.of(context).size`.
29
class MediaQueryData {
30 31 32 33
  /// Creates data for a media query with explicit values.
  ///
  /// Consider using [MediaQueryData.fromWindow] to create data based on a
  /// [ui.Window].
34 35 36 37 38 39
  const MediaQueryData({
    this.size: Size.zero,
    this.devicePixelRatio: 1.0,
    this.textScaleFactor: 1.0,
    this.padding: EdgeInsets.zero
  });
40

41
  /// Creates data for a media query based on the given window.
42
  MediaQueryData.fromWindow(ui.Window window)
43
    : size = window.physicalSize / window.devicePixelRatio,
44
      devicePixelRatio = window.devicePixelRatio,
45
      textScaleFactor = 1.0, // TODO(abarth): Read this value from window.
46
      padding = new EdgeInsets.fromWindowPadding(window.padding, window.devicePixelRatio);
47

48 49 50 51 52 53
  /// The size of the media in logical pixel (e.g, the size of the screen).
  ///
  /// Logical pixels are roughly the same visual size across devices. Physical
  /// pixels are the size of the actual hardware pixels on the device. The
  /// number of physical pixels per logical pixel is described by the
  /// [devicePixelRatio].
54 55
  final Size size;

56 57 58 59 60
  /// The number of device pixels for each logical pixel. This number might not
  /// be a power of two. Indeed, it might not even be an integer. For example,
  /// the Nexus 6 has a device pixel ratio of 3.5.
  final double devicePixelRatio;

61 62 63 64 65 66
  /// The number of font pixels for each logical pixel.
  ///
  /// For example, if the text scale factor is 1.5, text will be 50% larger than
  /// the specified font size.
  final double textScaleFactor;

67
  /// The padding around the edges of the media (e.g., the screen).
68
  final EdgeInsets padding;
69

70
  /// The orientation of the media (e.g., whether the device is in landscape or portrait mode).
71 72 73 74
  Orientation get orientation {
    return size.width > size.height ? Orientation.landscape : Orientation.portrait;
  }

75
  @override
76
  bool operator ==(Object other) {
77 78 79
    if (other.runtimeType != runtimeType)
      return false;
    MediaQueryData typedOther = other;
80
    return typedOther.size == size
81 82 83
        && typedOther.devicePixelRatio == devicePixelRatio
        && typedOther.textScaleFactor == textScaleFactor
        && typedOther.padding == padding;
84 85
  }

86
  @override
87
  int get hashCode => hashValues(size, devicePixelRatio, textScaleFactor, padding);
88

89
  @override
90
  String toString() => '$runtimeType(size: $size, devicePixelRatio: $devicePixelRatio, textScaleFactor: $textScaleFactor, padding: $padding)';
91 92
}

93
/// Establishes a subtree in which media queries resolve to the given data.
94 95 96 97 98 99 100 101 102
///
/// For example, to learn the size of the current media (e.g., the window
/// containing your app), you can read the [MediaQueryData.size] property from
/// the [MediaQueryData] returned by [MediaQuery.of]:
/// `MediaQuery.of(context).size`.
///
/// Querying the current media using [MediaQuery.of] will cause your widget to
/// rebuild automatically whenever the [MediaQueryData] changes (e.g., if the
/// user rotates their device).
103
class MediaQuery extends InheritedWidget {
104 105 106
  /// Creates a widget that provides [MediaQueryData] to its descendants.
  ///
  /// The [data] and [child] arguments must not be null.
107 108
  MediaQuery({
    Key key,
109 110
    @required this.data,
    @required Widget child
111 112 113 114 115
  }) : super(key: key, child: child) {
    assert(child != null);
    assert(data != null);
  }

116 117 118 119
  /// Contains information about the current media.
  ///
  /// For example, the [MediaQueryData.size] property contains the width and
  /// height of the current window.
120 121
  final MediaQueryData data;

122
  /// The data from the closest instance of this class that encloses the given context.
123 124 125 126
  ///
  /// You can use this function to query the size an orientation of the screen.
  /// When that information changes, your widget will be scheduled to be rebuilt,
  /// keeping your widget up-to-date.
127 128 129 130 131 132
  ///
  /// Typical usage is as follows:
  ///
  /// ```dart
  /// MediaQueryData media = MediaQuery.of(context);
  /// ```
133
  static MediaQueryData of(BuildContext context) {
Ian Hickson's avatar
Ian Hickson committed
134
    MediaQuery query = context.inheritFromWidgetOfExactType(MediaQuery);
135
    return query?.data ?? new MediaQueryData.fromWindow(ui.window);
136 137
  }

138
  @override
139 140
  bool updateShouldNotify(MediaQuery old) => data != old.data;

141
  @override
142 143 144 145 146
  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    description.add('$data');
  }
}