Merge pull request #485 from abarth/mimic
Add widgets for reparenting widgets
This commit is contained in:
commit
be75ee726d
90
packages/flutter/example/widgets/pop_out_and_expand.dart
Normal file
90
packages/flutter/example/widgets/pop_out_and_expand.dart
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// 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 'package:sky/painting/box_painter.dart';
|
||||||
|
import 'package:sky/widgets.dart';
|
||||||
|
|
||||||
|
class Circle extends Component {
|
||||||
|
Circle({ this.child });
|
||||||
|
|
||||||
|
Widget child;
|
||||||
|
|
||||||
|
Widget build() {
|
||||||
|
return new Container(
|
||||||
|
height: 100.0,
|
||||||
|
margin: new EdgeDims.symmetric(horizontal: 20.0, vertical: 4.0),
|
||||||
|
decoration: new BoxDecoration(
|
||||||
|
backgroundColor: const Color(0xFF0000FF)
|
||||||
|
),
|
||||||
|
child: new Center(
|
||||||
|
child: child
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CircleData {
|
||||||
|
final GlobalKey key;
|
||||||
|
final String content;
|
||||||
|
|
||||||
|
CircleData({ this.key, this.content });
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleApp extends App {
|
||||||
|
ExampleApp() {
|
||||||
|
for (int i = 0; i < 20; ++i) {
|
||||||
|
_data.add(new CircleData(
|
||||||
|
key: new GlobalKey(),
|
||||||
|
content: '$i'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<CircleData> _data = new List<CircleData>();
|
||||||
|
|
||||||
|
GlobalKey _keyToMimic;
|
||||||
|
|
||||||
|
Widget _buildCircle(CircleData circleData) {
|
||||||
|
return new Mimicable(
|
||||||
|
key: circleData.key,
|
||||||
|
child: new Listener(
|
||||||
|
child: new Circle(
|
||||||
|
child: new Text(circleData.content)
|
||||||
|
),
|
||||||
|
onGestureTap: (_) {
|
||||||
|
setState(() {
|
||||||
|
_keyToMimic = circleData.key;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget build() {
|
||||||
|
List<Widget> circles = new List<Widget>();
|
||||||
|
for (int i = 0; i < 20; ++i) {
|
||||||
|
circles.add(_buildCircle(_data[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> layers = new List<Widget>();
|
||||||
|
layers.add(new ScrollableBlock(circles));
|
||||||
|
|
||||||
|
if (_keyToMimic != null) {
|
||||||
|
layers.add(
|
||||||
|
new Positioned(
|
||||||
|
top: 50.0,
|
||||||
|
left: 50.0,
|
||||||
|
child: new Mimic(
|
||||||
|
original: _keyToMimic)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Stack(layers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
runApp(new ExampleApp());
|
||||||
|
}
|
@ -21,11 +21,14 @@ export 'widgets/drawer_item.dart';
|
|||||||
export 'widgets/flat_button.dart';
|
export 'widgets/flat_button.dart';
|
||||||
export 'widgets/floating_action_button.dart';
|
export 'widgets/floating_action_button.dart';
|
||||||
export 'widgets/focus.dart';
|
export 'widgets/focus.dart';
|
||||||
export 'widgets/icon_button.dart';
|
export 'widgets/framework.dart';
|
||||||
export 'widgets/icon.dart';
|
export 'widgets/icon.dart';
|
||||||
|
export 'widgets/icon_button.dart';
|
||||||
export 'widgets/ink_well.dart';
|
export 'widgets/ink_well.dart';
|
||||||
export 'widgets/material_button.dart';
|
|
||||||
export 'widgets/material.dart';
|
export 'widgets/material.dart';
|
||||||
|
export 'widgets/material_button.dart';
|
||||||
|
export 'widgets/mimic.dart';
|
||||||
|
export 'widgets/mimic.dart';
|
||||||
export 'widgets/modal_overlay.dart';
|
export 'widgets/modal_overlay.dart';
|
||||||
export 'widgets/navigator.dart';
|
export 'widgets/navigator.dart';
|
||||||
export 'widgets/popup_menu.dart';
|
export 'widgets/popup_menu.dart';
|
||||||
@ -41,4 +44,3 @@ export 'widgets/task_description.dart';
|
|||||||
export 'widgets/theme.dart';
|
export 'widgets/theme.dart';
|
||||||
export 'widgets/tool_bar.dart';
|
export 'widgets/tool_bar.dart';
|
||||||
export 'widgets/transitions.dart';
|
export 'widgets/transitions.dart';
|
||||||
export 'widgets/framework.dart';
|
|
||||||
|
@ -110,6 +110,11 @@ abstract class GlobalKey extends Key {
|
|||||||
assert(removed);
|
assert(removed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Widget getWidget(GlobalKey key) {
|
||||||
|
assert(key != null);
|
||||||
|
return _registry[key];
|
||||||
|
}
|
||||||
|
|
||||||
static void _notifyListeners() {
|
static void _notifyListeners() {
|
||||||
assert(!_inRenderDirtyComponents);
|
assert(!_inRenderDirtyComponents);
|
||||||
assert(!Widget._notifyingMountStatus);
|
assert(!Widget._notifyingMountStatus);
|
||||||
|
131
packages/flutter/lib/widgets/mimic.dart
Normal file
131
packages/flutter/lib/widgets/mimic.dart
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
// 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 'package:sky/widgets/basic.dart';
|
||||||
|
|
||||||
|
class Mimic extends StatefulComponent {
|
||||||
|
Mimic({ Key key, this.original }) : super(key: key);
|
||||||
|
|
||||||
|
GlobalKey original;
|
||||||
|
|
||||||
|
void initState() {
|
||||||
|
_requestToStartMimic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void syncFields(Mimic source) {
|
||||||
|
if (original != source.original) {
|
||||||
|
_stopMimic();
|
||||||
|
original = source.original;
|
||||||
|
_requestToStartMimic();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void didMount() {
|
||||||
|
super.didMount();
|
||||||
|
// TODO(abarth): Why is didMount being called without a call to didUnmount?
|
||||||
|
if (_mimicable == null)
|
||||||
|
_requestToStartMimic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void didUnmount() {
|
||||||
|
super.didUnmount();
|
||||||
|
_stopMimic();
|
||||||
|
}
|
||||||
|
|
||||||
|
Mimicable _mimicable;
|
||||||
|
Size _size;
|
||||||
|
|
||||||
|
void _requestToStartMimic() {
|
||||||
|
assert(_mimicable == null);
|
||||||
|
assert(_size == null);
|
||||||
|
if (original == null)
|
||||||
|
return;
|
||||||
|
_mimicable = GlobalKey.getWidget(original) as Mimicable;
|
||||||
|
assert(_mimicable != null);
|
||||||
|
_mimicable._requestToStartMimic(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _startMimic(GlobalKey key, Size size) {
|
||||||
|
assert(key == original);
|
||||||
|
setState(() {
|
||||||
|
_size = size;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _stopMimic() {
|
||||||
|
if (_mimicable != null)
|
||||||
|
_mimicable._didStopMimic(this);
|
||||||
|
_mimicable = null;
|
||||||
|
_size = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget build() {
|
||||||
|
if (_size == null || !_mimicable.mounted)
|
||||||
|
return new Container();
|
||||||
|
return new ConstrainedBox(
|
||||||
|
constraints: new BoxConstraints.tight(_size),
|
||||||
|
child: _mimicable.child
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Mimicable extends StatefulComponent {
|
||||||
|
Mimicable({ GlobalKey key, this.child }) : super(key: key);
|
||||||
|
|
||||||
|
Widget child;
|
||||||
|
|
||||||
|
Size _size;
|
||||||
|
Size get size => _size;
|
||||||
|
|
||||||
|
Mimic _mimic;
|
||||||
|
bool _didStartMimic = false;
|
||||||
|
|
||||||
|
void syncFields(Mimicable source) {
|
||||||
|
child = source.child;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _requestToStartMimic(Mimic mimic) {
|
||||||
|
assert(mounted);
|
||||||
|
if (_mimic != null)
|
||||||
|
return;
|
||||||
|
setState(() {
|
||||||
|
_mimic = mimic;
|
||||||
|
_didStartMimic = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _didStopMimic(Mimic mimic) {
|
||||||
|
assert(_mimic != null);
|
||||||
|
assert(mimic == _mimic);
|
||||||
|
setState(() {
|
||||||
|
_mimic = null;
|
||||||
|
_didStartMimic = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleSizeChanged(Size size) {
|
||||||
|
setState(() {
|
||||||
|
_size = size;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _startMimicIfNeeded() {
|
||||||
|
if (_didStartMimic)
|
||||||
|
return;
|
||||||
|
assert(_mimic != null);
|
||||||
|
_mimic._startMimic(key, _size);
|
||||||
|
_didStartMimic = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget build() {
|
||||||
|
if (_mimic != null) {
|
||||||
|
_startMimicIfNeeded();
|
||||||
|
return new ConstrainedBox(constraints: new BoxConstraints.tight(_size));
|
||||||
|
}
|
||||||
|
return new SizeObserver(
|
||||||
|
callback: _handleSizeChanged,
|
||||||
|
child: child
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user