Remove ChildView widget (#6195)
This widget now lives in Mozart: https://fuchsia.googlesource.com/mozart/+/master/lib/flutter/child_view.dart
This commit is contained in:
parent
8071a82d51
commit
67f97b455d
@ -1,254 +0,0 @@
|
||||
// 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 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LauncherData {
|
||||
const LauncherData({ this.url, this.title });
|
||||
final String url;
|
||||
final String title;
|
||||
}
|
||||
|
||||
final List<LauncherData> _kLauncherData = <LauncherData>[
|
||||
const LauncherData(
|
||||
url: 'mojo:noodles_view',
|
||||
title: 'Noodles'
|
||||
),
|
||||
const LauncherData(
|
||||
url: 'mojo:shapes_view',
|
||||
title: 'Shapes'
|
||||
),
|
||||
new LauncherData(
|
||||
url: Uri.base.resolve('../../../examples/stocks/build/app.flx').toString(),
|
||||
title: 'Stocks'
|
||||
),
|
||||
];
|
||||
|
||||
const Size _kInitialWindowSize = const Size(200.0, 200.0);
|
||||
const double _kWindowPadding = 10.0;
|
||||
|
||||
enum WindowSide {
|
||||
topCenter,
|
||||
topRight,
|
||||
bottomRight,
|
||||
}
|
||||
|
||||
class WindowDecoration extends StatelessWidget {
|
||||
WindowDecoration({
|
||||
Key key,
|
||||
this.side,
|
||||
this.color,
|
||||
this.onTap,
|
||||
this.onPanUpdate
|
||||
}) : super(key: key);
|
||||
|
||||
final WindowSide side;
|
||||
final Color color;
|
||||
final GestureTapCallback onTap;
|
||||
final GestureDragUpdateCallback onPanUpdate;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double top, right, bottom, left, width, height;
|
||||
|
||||
height = _kWindowPadding * 2.0;
|
||||
|
||||
if (side == WindowSide.topCenter || side == WindowSide.topRight)
|
||||
top = 0.0;
|
||||
|
||||
if (side == WindowSide.topRight || side == WindowSide.bottomRight) {
|
||||
right = 0.0;
|
||||
width = _kWindowPadding * 2.0;
|
||||
}
|
||||
|
||||
if (side == WindowSide.topCenter) {
|
||||
left = _kWindowPadding;
|
||||
right = _kWindowPadding;
|
||||
}
|
||||
|
||||
if (side == WindowSide.bottomRight)
|
||||
bottom = 0.0;
|
||||
|
||||
return new Positioned(
|
||||
top: top,
|
||||
right: right,
|
||||
bottom: bottom,
|
||||
left: left,
|
||||
width: width,
|
||||
height: height,
|
||||
child: new GestureDetector(
|
||||
onTap: onTap,
|
||||
onPanUpdate: onPanUpdate,
|
||||
child: new Container(
|
||||
decoration: new BoxDecoration(
|
||||
backgroundColor: color
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Window extends StatefulWidget {
|
||||
Window({ Key key, this.child, this.onClose }) : super(key: key);
|
||||
|
||||
final ChildViewConnection child;
|
||||
final ValueChanged<ChildViewConnection> onClose;
|
||||
|
||||
@override
|
||||
_WindowState createState() => new _WindowState();
|
||||
}
|
||||
|
||||
class _WindowState extends State<Window> {
|
||||
Offset _offset = Offset.zero;
|
||||
Size _size = _kInitialWindowSize;
|
||||
|
||||
void _handleResizerDrag(DragUpdateDetails details) {
|
||||
setState(() {
|
||||
_size = new Size(
|
||||
math.max(0.0, _size.width + details.delta.dx),
|
||||
math.max(0.0, _size.height + details.delta.dy)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
void _handleRepositionDrag(DragUpdateDetails details) {
|
||||
setState(() {
|
||||
_offset += details.delta;
|
||||
});
|
||||
}
|
||||
|
||||
void _handleClose() {
|
||||
config.onClose(config.child);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new Positioned(
|
||||
left: _offset.dx,
|
||||
top: _offset.dy,
|
||||
width: _size.width + _kWindowPadding * 2.0,
|
||||
height: _size.height + _kWindowPadding * 2.0,
|
||||
child: new Stack(
|
||||
children: <Widget>[
|
||||
new WindowDecoration(
|
||||
side: WindowSide.topCenter,
|
||||
onPanUpdate: _handleRepositionDrag,
|
||||
color: Colors.green[200]
|
||||
),
|
||||
new WindowDecoration(
|
||||
side: WindowSide.topRight,
|
||||
onTap: _handleClose,
|
||||
color: Colors.red[200]
|
||||
),
|
||||
new WindowDecoration(
|
||||
side: WindowSide.bottomRight,
|
||||
onPanUpdate: _handleResizerDrag,
|
||||
color: Colors.blue[200]
|
||||
),
|
||||
new Container(
|
||||
padding: const EdgeInsets.all(_kWindowPadding),
|
||||
child: new Material(
|
||||
elevation: 8,
|
||||
child: new ChildView(child: config.child)
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LauncherItem extends StatelessWidget {
|
||||
LauncherItem({
|
||||
Key key,
|
||||
this.url,
|
||||
this.child,
|
||||
this.onLaunch
|
||||
}) : super(key: key);
|
||||
|
||||
final String url;
|
||||
final Widget child;
|
||||
final ValueChanged<ChildViewConnection> onLaunch;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new RaisedButton(
|
||||
onPressed: () { onLaunch(new ChildViewConnection(url: url)); },
|
||||
child: child
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Launcher extends StatelessWidget {
|
||||
Launcher({ Key key, this.items }) : super(key: key);
|
||||
|
||||
final List<Widget> items;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new ButtonBar(
|
||||
alignment: MainAxisAlignment.center,
|
||||
children: items
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class WindowManager extends StatefulWidget {
|
||||
@override
|
||||
_WindowManagerState createState() => new _WindowManagerState();
|
||||
}
|
||||
|
||||
class _WindowManagerState extends State<WindowManager> {
|
||||
List<ChildViewConnection> _windows = <ChildViewConnection>[];
|
||||
|
||||
void _handleLaunch(ChildViewConnection child) {
|
||||
setState(() {
|
||||
_windows.add(child);
|
||||
});
|
||||
}
|
||||
|
||||
void _handleClose(ChildViewConnection child) {
|
||||
setState(() {
|
||||
_windows.remove(child);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new Material(
|
||||
child: new Stack(
|
||||
children: <Widget>[
|
||||
new Positioned(
|
||||
left: 0.0,
|
||||
right: 0.0,
|
||||
bottom: 0.0,
|
||||
child: new Launcher(items: _kLauncherData.map((LauncherData data) {
|
||||
return new LauncherItem(
|
||||
url: data.url,
|
||||
onLaunch: _handleLaunch,
|
||||
child: new Text(data.title)
|
||||
);
|
||||
}).toList())
|
||||
)
|
||||
]..addAll(_windows.map((ChildViewConnection child) {
|
||||
return new Window(
|
||||
key: new ObjectKey(child),
|
||||
onClose: _handleClose,
|
||||
child: child
|
||||
);
|
||||
}))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
runApp(new MaterialApp(
|
||||
title: 'Mozart',
|
||||
home: new WindowManager()
|
||||
));
|
||||
}
|
@ -27,7 +27,6 @@ export 'src/rendering/auto_layout.dart';
|
||||
export 'src/rendering/binding.dart';
|
||||
export 'src/rendering/block.dart';
|
||||
export 'src/rendering/box.dart';
|
||||
export 'src/rendering/child_view.dart';
|
||||
export 'src/rendering/custom_layout.dart';
|
||||
export 'src/rendering/debug.dart';
|
||||
export 'src/rendering/editable_line.dart';
|
||||
|
@ -1,336 +0,0 @@
|
||||
// Copyright 2016 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 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_services/mojo/gfx/composition/scene_token.dart' as mojom;
|
||||
import 'package:flutter_services/mojo/ui/view_containers.dart' as mojom;
|
||||
import 'package:flutter_services/mojo/ui/view_provider.dart' as mojom;
|
||||
import 'package:flutter_services/mojo/ui/view_properties.dart' as mojom;
|
||||
import 'package:flutter_services/mojo/ui/view_token.dart' as mojom;
|
||||
import 'package:flutter_services/mojo/ui/views.dart' as mojom;
|
||||
import 'package:flutter_services/mojo/geometry.dart' as mojom;
|
||||
import 'package:mojo/application.dart';
|
||||
import 'package:mojo/core.dart' as core;
|
||||
import 'package:mojo/mojo/service_provider.mojom.dart' as mojom;
|
||||
|
||||
import 'box.dart';
|
||||
import 'object.dart';
|
||||
import 'layer.dart';
|
||||
|
||||
mojom.ViewProxy _initViewProxy() {
|
||||
int viewHandle = ui.MojoServices.takeView();
|
||||
if (viewHandle == core.MojoHandle.INVALID)
|
||||
return null;
|
||||
return new mojom.ViewProxy.fromHandle(new core.MojoHandle(viewHandle));
|
||||
}
|
||||
|
||||
// TODO(abarth): The view host is a unique resource. We should structure how we
|
||||
// take the handle from the engine so that multiple libraries can interact with
|
||||
// the view host safely. Unfortunately, the view host has a global namespace of
|
||||
// view keys, which means any scheme for sharing the view host also needs to
|
||||
// provide a mechanism for coordinating about view keys.
|
||||
final mojom.ViewProxy _viewProxy = _initViewProxy();
|
||||
final mojom.View _view = _viewProxy;
|
||||
|
||||
mojom.ViewContainer _initViewContainer() {
|
||||
if (_view == null)
|
||||
return null;
|
||||
mojom.ViewContainerProxy viewContainerProxy = new mojom.ViewContainerProxy.unbound();
|
||||
_view.getContainer(viewContainerProxy);
|
||||
viewContainerProxy.setListener(new mojom.ViewContainerListenerStub.unbound()..impl = _ViewContainerListenerImpl.instance);
|
||||
return viewContainerProxy;
|
||||
}
|
||||
|
||||
final mojom.ViewContainer _viewContainer = _initViewContainer();
|
||||
|
||||
typedef dynamic _ResponseFactory();
|
||||
|
||||
class _ViewContainerListenerImpl extends mojom.ViewContainerListener {
|
||||
static final _ViewContainerListenerImpl instance = new _ViewContainerListenerImpl();
|
||||
|
||||
@override
|
||||
dynamic onChildAttached(int childKey, mojom.ViewInfo childViewInfo, [_ResponseFactory responseFactory = null]) {
|
||||
ChildViewConnection connection = _connections[childKey];
|
||||
connection?._onAttachedToContainer(childViewInfo);
|
||||
return responseFactory();
|
||||
}
|
||||
|
||||
@override
|
||||
dynamic onChildUnavailable(int childKey, [_ResponseFactory responseFactory = null]) {
|
||||
ChildViewConnection connection = _connections[childKey];
|
||||
connection?._onUnavailable();
|
||||
return responseFactory();
|
||||
}
|
||||
|
||||
final Map<int, ChildViewConnection> _connections = new HashMap<int, ChildViewConnection>();
|
||||
}
|
||||
|
||||
/// (mojo-only) A connection with a child view.
|
||||
///
|
||||
/// Used with the [ChildView] widget to display a child view.
|
||||
class ChildViewConnection {
|
||||
/// Establishes a connection to the app at the given URL.
|
||||
ChildViewConnection({ String url }) {
|
||||
mojom.ViewProviderProxy viewProvider = shell.connectToApplicationService(
|
||||
url, mojom.ViewProvider.connectToService
|
||||
);
|
||||
mojom.ServiceProviderProxy incomingServices = new mojom.ServiceProviderProxy.unbound();
|
||||
_viewOwner = new mojom.ViewOwnerProxy.unbound();
|
||||
viewProvider.createView(_viewOwner, incomingServices);
|
||||
viewProvider.close();
|
||||
_connection = new ApplicationConnection(null, incomingServices);
|
||||
}
|
||||
|
||||
/// Wraps an already-established connection to a child app.
|
||||
ChildViewConnection.fromViewOwner({
|
||||
mojom.ViewOwnerProxy viewOwner,
|
||||
ApplicationConnection connection
|
||||
}) : _connection = connection, _viewOwner = viewOwner;
|
||||
|
||||
/// The underlying application connection to the child app.
|
||||
///
|
||||
/// Useful for requesting services from the child app and for providing
|
||||
/// services to the child app.
|
||||
ApplicationConnection get connection => _connection;
|
||||
ApplicationConnection _connection;
|
||||
|
||||
mojom.ViewOwnerProxy _viewOwner;
|
||||
|
||||
static int _nextViewKey = 1;
|
||||
int _viewKey;
|
||||
|
||||
int _sceneVersion = 1;
|
||||
mojom.ViewProperties _currentViewProperties;
|
||||
|
||||
VoidCallback _onViewInfoAvailable;
|
||||
mojom.ViewInfo _viewInfo;
|
||||
|
||||
void _onAttachedToContainer(mojom.ViewInfo viewInfo) {
|
||||
assert(_viewInfo == null);
|
||||
_viewInfo = viewInfo;
|
||||
if (_onViewInfoAvailable != null)
|
||||
_onViewInfoAvailable();
|
||||
}
|
||||
|
||||
void _onUnavailable() {
|
||||
_viewInfo = null;
|
||||
}
|
||||
|
||||
void _addChildToViewHost() {
|
||||
assert(_attached);
|
||||
assert(_viewOwner != null);
|
||||
assert(_viewKey == null);
|
||||
assert(_viewInfo == null);
|
||||
_viewKey = _nextViewKey++;
|
||||
_viewContainer?.addChild(_viewKey, _viewOwner);
|
||||
_viewOwner = null;
|
||||
assert(!_ViewContainerListenerImpl.instance._connections.containsKey(_viewKey));
|
||||
_ViewContainerListenerImpl.instance._connections[_viewKey] = this;
|
||||
}
|
||||
|
||||
void _removeChildFromViewHost() {
|
||||
assert(!_attached);
|
||||
assert(_viewOwner == null);
|
||||
assert(_viewKey != null);
|
||||
assert(_ViewContainerListenerImpl.instance._connections[_viewKey] == this);
|
||||
_ViewContainerListenerImpl.instance._connections.remove(_viewKey);
|
||||
_viewOwner = new mojom.ViewOwnerProxy.unbound();
|
||||
_viewContainer?.removeChild(_viewKey, _viewOwner);
|
||||
_viewKey = null;
|
||||
_viewInfo = null;
|
||||
_currentViewProperties = null;
|
||||
}
|
||||
|
||||
// The number of render objects attached to this view. In between frames, we
|
||||
// might have more than one connected if we get added to a new render object
|
||||
// before we get removed from the old render object. By the time we get around
|
||||
// to computing our layout, we must be back to just having one render object.
|
||||
int _attachments = 0;
|
||||
bool get _attached => _attachments > 0;
|
||||
|
||||
void _attach() {
|
||||
assert(_attachments >= 0);
|
||||
++_attachments;
|
||||
if (_viewKey == null)
|
||||
_addChildToViewHost();
|
||||
}
|
||||
|
||||
void _detach() {
|
||||
assert(_attached);
|
||||
--_attachments;
|
||||
scheduleMicrotask(_removeChildFromViewHostIfNeeded);
|
||||
}
|
||||
|
||||
void _removeChildFromViewHostIfNeeded() {
|
||||
assert(_attachments >= 0);
|
||||
if (_attachments == 0)
|
||||
_removeChildFromViewHost();
|
||||
}
|
||||
|
||||
mojom.ViewProperties _createViewProperties(int physicalWidth,
|
||||
int physicalHeight,
|
||||
double devicePixelRatio) {
|
||||
if (_currentViewProperties != null &&
|
||||
_currentViewProperties.displayMetrics.devicePixelRatio == devicePixelRatio &&
|
||||
_currentViewProperties.viewLayout.size.width == physicalWidth &&
|
||||
_currentViewProperties.viewLayout.size.height == physicalHeight)
|
||||
return null;
|
||||
|
||||
mojom.DisplayMetrics displayMetrics = new mojom.DisplayMetrics()
|
||||
..devicePixelRatio = devicePixelRatio;
|
||||
mojom.Size size = new mojom.Size()
|
||||
..width = physicalWidth
|
||||
..height = physicalHeight;
|
||||
mojom.ViewLayout viewLayout = new mojom.ViewLayout()
|
||||
..size = size;
|
||||
_currentViewProperties = new mojom.ViewProperties()
|
||||
..displayMetrics = displayMetrics
|
||||
..viewLayout = viewLayout;
|
||||
return _currentViewProperties;
|
||||
}
|
||||
|
||||
void _setChildProperties(int physicalWidth, int physicalHeight, double devicePixelRatio) {
|
||||
assert(_attached);
|
||||
assert(_attachments == 1);
|
||||
assert(_viewKey != null);
|
||||
if (_view == null)
|
||||
return;
|
||||
mojom.ViewProperties viewProperties = _createViewProperties(physicalWidth, physicalHeight, devicePixelRatio);
|
||||
if (viewProperties == null)
|
||||
return;
|
||||
_viewContainer.setChildProperties(_viewKey, _sceneVersion++, viewProperties);
|
||||
}
|
||||
}
|
||||
|
||||
/// (mojo-only) A view of a child application.
|
||||
class RenderChildView extends RenderBox {
|
||||
/// Creates a child view render object.
|
||||
///
|
||||
/// The [scale] argument must not be null.
|
||||
RenderChildView({
|
||||
ChildViewConnection child,
|
||||
double scale
|
||||
}) : _scale = scale {
|
||||
assert(scale != null);
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
/// The child to display.
|
||||
ChildViewConnection get child => _child;
|
||||
ChildViewConnection _child;
|
||||
set child (ChildViewConnection value) {
|
||||
if (value == _child)
|
||||
return;
|
||||
if (attached && _child != null) {
|
||||
_child._detach();
|
||||
assert(_child._onViewInfoAvailable != null);
|
||||
_child._onViewInfoAvailable = null;
|
||||
}
|
||||
_child = value;
|
||||
if (attached && _child != null) {
|
||||
_child._attach();
|
||||
assert(_child._onViewInfoAvailable == null);
|
||||
_child._onViewInfoAvailable = markNeedsPaint;
|
||||
}
|
||||
if (_child == null) {
|
||||
markNeedsPaint();
|
||||
} else {
|
||||
markNeedsLayout();
|
||||
}
|
||||
}
|
||||
|
||||
/// The device pixel ratio to provide the child.
|
||||
double get scale => _scale;
|
||||
double _scale;
|
||||
set scale (double value) {
|
||||
assert(value != null);
|
||||
if (value == _scale)
|
||||
return;
|
||||
_scale = value;
|
||||
if (_child != null)
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
@override
|
||||
void attach(PipelineOwner owner) {
|
||||
super.attach(owner);
|
||||
if (_child != null) {
|
||||
_child._attach();
|
||||
assert(_child._onViewInfoAvailable == null);
|
||||
_child._onViewInfoAvailable = markNeedsPaint;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void detach() {
|
||||
if (_child != null) {
|
||||
_child._detach();
|
||||
assert(_child._onViewInfoAvailable != null);
|
||||
_child._onViewInfoAvailable = null;
|
||||
}
|
||||
super.detach();
|
||||
}
|
||||
|
||||
@override
|
||||
bool get alwaysNeedsCompositing => true;
|
||||
|
||||
TextPainter _debugErrorMessage;
|
||||
|
||||
int _physicalWidth;
|
||||
int _physicalHeight;
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
size = constraints.biggest;
|
||||
if (_child != null) {
|
||||
_physicalWidth = (size.width * scale).round();
|
||||
_physicalHeight = (size.height * scale).round();
|
||||
_child._setChildProperties(_physicalWidth, _physicalHeight, scale);
|
||||
assert(() {
|
||||
if (_view == null) {
|
||||
_debugErrorMessage ??= new TextPainter(
|
||||
text: new TextSpan(text: 'Child views are supported only when running in Mojo shell.')
|
||||
);
|
||||
_debugErrorMessage.layout(minWidth: size.width, maxWidth: size.width);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool hitTestSelf(Point position) => true;
|
||||
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
assert(needsCompositing);
|
||||
if (_child?._viewInfo != null) {
|
||||
context.addLayer(new ChildSceneLayer(
|
||||
offset: offset,
|
||||
devicePixelRatio: scale,
|
||||
physicalWidth: _physicalWidth,
|
||||
physicalHeight: _physicalHeight,
|
||||
sceneToken: _child._viewInfo.sceneToken.value
|
||||
));
|
||||
}
|
||||
assert(() {
|
||||
if (_view == null) {
|
||||
context.canvas.drawRect(offset & size, new Paint()..color = const Color(0xFF0000FF));
|
||||
_debugErrorMessage.paint(context.canvas, offset);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void debugFillDescription(List<String> description) {
|
||||
super.debugFillDescription(description);
|
||||
description.add('child: $child');
|
||||
description.add('scale: $scale');
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
// Copyright 2016 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:flutter/rendering.dart';
|
||||
|
||||
import 'framework.dart';
|
||||
import 'media_query.dart';
|
||||
|
||||
export 'package:flutter/rendering.dart' show ChildViewConnection;
|
||||
|
||||
/// (mojo-only) A widget that is replaced by content from another process.
|
||||
///
|
||||
/// Requires a [MediaQuery] ancestor to provide appropriate media information to
|
||||
/// the child.
|
||||
class ChildView extends StatelessWidget {
|
||||
/// Creates a widget that is replaced by content from another process.
|
||||
ChildView({ Key key, this.child }) : super(key: key);
|
||||
|
||||
/// A connection to the child whose content will replace this widget.
|
||||
final ChildViewConnection child;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new _ChildViewWidget(
|
||||
child: child,
|
||||
scale: MediaQuery.of(context).devicePixelRatio
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ChildViewWidget extends LeafRenderObjectWidget {
|
||||
_ChildViewWidget({
|
||||
ChildViewConnection child,
|
||||
this.scale
|
||||
}) : child = child, super(key: new GlobalObjectKey(child)) {
|
||||
assert(scale != null);
|
||||
}
|
||||
|
||||
final ChildViewConnection child;
|
||||
final double scale;
|
||||
|
||||
@override
|
||||
RenderChildView createRenderObject(BuildContext context) => new RenderChildView(child: child, scale: scale);
|
||||
|
||||
@override
|
||||
void updateRenderObject(BuildContext context, RenderChildView renderObject) {
|
||||
renderObject
|
||||
..child = child
|
||||
..scale = scale;
|
||||
}
|
||||
}
|
@ -15,7 +15,6 @@ export 'src/widgets/auto_layout.dart';
|
||||
export 'src/widgets/banner.dart';
|
||||
export 'src/widgets/basic.dart';
|
||||
export 'src/widgets/binding.dart';
|
||||
export 'src/widgets/child_view.dart';
|
||||
export 'src/widgets/clamp_overscrolls.dart';
|
||||
export 'src/widgets/container.dart';
|
||||
export 'src/widgets/debug.dart';
|
||||
|
Loading…
x
Reference in New Issue
Block a user