From 6c2bbff4ad40186ffcc1209730d239d790ae4033 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Fri, 23 Oct 2015 13:58:37 -0700 Subject: [PATCH] Media query class for querying viewport information --- examples/widgets/media_query.dart | 100 ++++++++++++++++++ .../lib/src/material/material_app.dart | 37 ++++--- .../flutter/lib/src/widgets/media_query.dart | 55 ++++++++++ packages/flutter/lib/widgets.dart | 1 + 4 files changed, 181 insertions(+), 12 deletions(-) create mode 100644 examples/widgets/media_query.dart create mode 100644 packages/flutter/lib/src/widgets/media_query.dart diff --git a/examples/widgets/media_query.dart b/examples/widgets/media_query.dart new file mode 100644 index 00000000000..a54fd859285 --- /dev/null +++ b/examples/widgets/media_query.dart @@ -0,0 +1,100 @@ +import 'package:flutter/material.dart'; + +void main() { + runApp( + new MaterialApp( + title: "Media Query Example", + routes: { + '/': (RouteArguments args) => new MediaQueryExample() + } + ) + ); +} + +class AdaptiveItem { + AdaptiveItem(this.name); + String name; + + Widget toListItem() { + return new Row( + [ + new Container( + width: 32.0, + height: 32.0, + margin: const EdgeDims.all(8.0), + decoration: new BoxDecoration( + backgroundColor: Colors.lightBlueAccent[100] + ) + ), + new Text(name) + ] + ); + } + + Widget toCard() { + return new Card( + child: new Column( + [ + new Flexible( + child: new Container( + decoration: new BoxDecoration( + backgroundColor: Colors.lightBlueAccent[100] + ) + ) + ), + new Container( + margin: const EdgeDims.only(left: 8.0), + child: new Row( + [ + new Flexible( + child: new Text(name) + ), + new IconButton( + icon: "navigation/more_vert" + ) + ] + ) + ) + ] + ) + ); + } +} + +class MediaQueryExample extends StatelessComponent { + static const double _maxChildExtent = 150.0; + static const double _gridViewBreakpoint = 450.0; + + Widget _buildBody(BuildContext context) { + List items = []; + + for (int i = 0; i < 30; i++) + items.add(new AdaptiveItem("Item $i")); + + if (MediaQuery.of(context).size.width < _gridViewBreakpoint) { + return new Block( + items.map((AdaptiveItem item) => item.toListItem()).toList() + ); + } else { + return new Block( + [ + new Grid( + items.map((AdaptiveItem item) => item.toCard()).toList(), + maxChildExtent: _maxChildExtent + ) + ] + ); + } + } + + Widget build(BuildContext context) { + return new Scaffold( + toolBar: new ToolBar( + center: new Text("Media Query Example") + ), + body: new Material( + child: _buildBody(context) + ) + ); + } +} diff --git a/packages/flutter/lib/src/material/material_app.dart b/packages/flutter/lib/src/material/material_app.dart index 75a59ea546f..9624f1e2543 100644 --- a/packages/flutter/lib/src/material/material_app.dart +++ b/packages/flutter/lib/src/material/material_app.dart @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:ui' as ui; + +import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; @@ -49,14 +52,19 @@ class _MaterialAppState extends State { GlobalObjectKey _navigator; + Size _size; + void initState() { super.initState(); _navigator = new GlobalObjectKey(this); WidgetFlutterBinding.instance.addEventListener(_backHandler); + _size = ui.window.size; + FlutterBinding.instance.addMetricListener(_metricHandler); } void dispose() { WidgetFlutterBinding.instance.removeEventListener(_backHandler); + FlutterBinding.instance.removeMetricListener(_metricHandler); super.dispose(); } @@ -72,19 +80,24 @@ class _MaterialAppState extends State { } } + void _metricHandler(Size size) => setState(() { _size = size; }); + Widget build(BuildContext context) { - return new Theme( - data: config.theme ?? new ThemeData.fallback(), - child: new DefaultTextStyle( - style: _errorTextStyle, - child: new DefaultAssetBundle( - bundle: _defaultBundle, - child: new Title( - title: config.title, - child: new Navigator( - key: _navigator, - routes: config.routes, - onGenerateRoute: config.onGenerateRoute + return new MediaQuery( + data: new MediaQueryData(size: _size), + child: new Theme( + data: config.theme ?? new ThemeData.fallback(), + child: new DefaultTextStyle( + style: _errorTextStyle, + child: new DefaultAssetBundle( + bundle: _defaultBundle, + child: new Title( + title: config.title, + child: new Navigator( + key: _navigator, + routes: config.routes, + onGenerateRoute: config.onGenerateRoute + ) ) ) ) diff --git a/packages/flutter/lib/src/widgets/media_query.dart b/packages/flutter/lib/src/widgets/media_query.dart new file mode 100644 index 00000000000..5640c478363 --- /dev/null +++ b/packages/flutter/lib/src/widgets/media_query.dart @@ -0,0 +1,55 @@ +// 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. + +import 'basic.dart'; +import 'framework.dart'; + +enum Orientation { portrait, landscape } + +class MediaQueryData { + + const MediaQueryData({ this.size }); + + final Size size; + + Orientation get orientation { + return size.width > size.height ? Orientation.landscape : Orientation.portrait; + } + + bool operator==(Object other) { + if (other.runtimeType != runtimeType) + return false; + MediaQueryData typedOther = other; + return typedOther.size == size; + } + + int get hashCode => size.hashCode; + + String toString() => '$runtimeType($size, $orientation)'; +} + +class MediaQuery extends InheritedWidget { + MediaQuery({ + Key key, + this.data, + Widget child + }) : super(key: key, child: child) { + assert(child != null); + assert(data != null); + } + + final MediaQueryData data; + + static MediaQueryData of(BuildContext context) { + MediaQuery query = context.inheritedWidgetOfType(MediaQuery); + return query == null ? null : query.data; + } + + bool updateShouldNotify(MediaQuery old) => data != old.data; + + void debugFillDescription(List description) { + super.debugFillDescription(description); + description.add('$data'); + } +} diff --git a/packages/flutter/lib/widgets.dart b/packages/flutter/lib/widgets.dart index a18ebef3d7a..208acb47492 100644 --- a/packages/flutter/lib/widgets.dart +++ b/packages/flutter/lib/widgets.dart @@ -18,6 +18,7 @@ export 'src/widgets/gesture_detector.dart'; export 'src/widgets/gridpaper.dart'; export 'src/widgets/heroes.dart'; export 'src/widgets/homogeneous_viewport.dart'; +export 'src/widgets/media_query.dart'; export 'src/widgets/mimic.dart'; export 'src/widgets/mixed_viewport.dart'; export 'src/widgets/navigator.dart';