Merge pull request #1476 from abarth/ink_well_gestures

RenderInkWell should use gestures
This commit is contained in:
Adam Barth 2015-10-03 12:53:03 -07:00
commit 44dbe3c77d
21 changed files with 320 additions and 207 deletions

View File

@ -42,8 +42,8 @@ void launch(String relativeUrl, String bundle) {
activity.startActivity(intent);
}
class SkyDemo {
SkyDemo({
class FlutterDemo {
FlutterDemo({
name,
this.href,
this.bundle,
@ -60,8 +60,8 @@ class SkyDemo {
final BoxDecoration decoration;
}
List<SkyDemo> demos = [
new SkyDemo(
List<FlutterDemo> demos = [
new FlutterDemo(
name: 'Stocks',
href: '../../stocks/lib/main.dart',
bundle: 'stocks.skyx',
@ -74,7 +74,7 @@ List<SkyDemo> demos = [
)
)
),
new SkyDemo(
new FlutterDemo(
name: 'Asteroids',
href: '../../game/lib/main.dart',
bundle: 'game.skyx',
@ -87,7 +87,7 @@ List<SkyDemo> demos = [
)
)
),
new SkyDemo(
new FlutterDemo(
name: 'Fitness',
href: '../../fitness/lib/main.dart',
bundle: 'fitness.skyx',
@ -97,7 +97,7 @@ List<SkyDemo> demos = [
backgroundColor: Colors.indigo[500]
)
),
new SkyDemo(
new FlutterDemo(
name: 'Swipe Away',
href: '../../widgets/card_collection.dart',
bundle: 'cards.skyx',
@ -107,7 +107,7 @@ List<SkyDemo> demos = [
backgroundColor: Colors.redAccent[200]
)
),
new SkyDemo(
new FlutterDemo(
name: 'Interactive Text',
href: '../../rendering/interactive_flex.dart',
bundle: 'interactive_flex.skyx',
@ -120,7 +120,7 @@ List<SkyDemo> demos = [
// new SkyDemo(
// 'Touch Demo', '../../rendering/touch_demo.dart', 'Simple example showing handling of touch events at a low level'),
new SkyDemo(
new FlutterDemo(
name: 'Minedigger Game',
href: '../../mine_digger/lib/main.dart',
bundle: 'mine_digger.skyx',
@ -138,44 +138,47 @@ List<SkyDemo> demos = [
const double kCardHeight = 120.0;
const EdgeDims kListPadding = const EdgeDims.all(4.0);
class DemoList extends StatelessComponent {
Widget buildCardContents(SkyDemo demo) {
return new Container(
decoration: demo.decoration,
child: new InkWell(
child: new Container(
margin: const EdgeDims.only(top: 24.0, left: 24.0),
child: new Column([
new Text(demo.name, style: demo.textTheme.title),
new Flexible(
child: new Text(demo.description, style: demo.textTheme.subhead)
)
],
alignItems: FlexAlignItems.start
class DemoCard extends StatelessComponent {
DemoCard({ Key key, this.demo }) : super(key: key);
final FlutterDemo demo;
Widget build(BuildContext context) {
return new Container(
height: kCardHeight,
child: new Card(
child: new Container(
decoration: demo.decoration,
child: new InkWell(
onTap: () => launch(demo.href, demo.bundle),
child: new Container(
margin: const EdgeDims.only(top: 24.0, left: 24.0),
child: new Column([
new Text(demo.name, style: demo.textTheme.title),
new Flexible(
child: new Text(demo.description, style: demo.textTheme.subhead)
)
],
alignItems: FlexAlignItems.start
)
)
)
)
);
}
Widget buildDemo(BuildContext context, SkyDemo demo) {
return new GestureDetector(
key: demo.key,
onTap: () => launch(demo.href, demo.bundle),
child: new Container(
height: kCardHeight,
child: new Card(
child: buildCardContents(demo)
)
)
);
}
}
class DemoList extends StatelessComponent {
Widget _buildDemoCard(BuildContext context, FlutterDemo demo) {
return new DemoCard(key: demo.key, demo: demo);
}
Widget build(BuildContext context) {
return new ScrollableList<SkyDemo>(
return new ScrollableList<FlutterDemo>(
items: demos,
itemExtent: kCardHeight,
itemBuilder: buildDemo,
itemBuilder: _buildDemoCard,
padding: kListPadding
);
}
@ -200,7 +203,7 @@ class DemoHome extends StatelessComponent {
void main() {
runApp(new App(
title: 'Sky Demos',
title: 'Flutter Demos',
theme: _theme,
routes: {
'/': (NavigatorState navigator, Route route) => new DemoHome()

View File

@ -33,15 +33,13 @@ class DialogMenuItem extends StatelessComponent {
Function onPressed;
Widget build(BuildContext context) {
return new GestureDetector(
onTap: onPressed,
child: new Container(
height: 48.0,
child: new InkWell(
child: new Padding(
padding: const EdgeDims.symmetric(horizontal: 16.0),
child: new Row(children)
)
return new Container(
height: 48.0,
child: new InkWell(
onTap: onPressed,
child: new Padding(
padding: const EdgeDims.symmetric(horizontal: 16.0),
child: new Row(children)
)
)
);

View File

@ -65,12 +65,13 @@ class MealFragmentState extends State<MealFragment> {
icon: "navigation/close",
onPressed: config.navigator.pop),
center: new Text('New Meal'),
right: [new InkWell(
child: new GestureDetector(
right: [
// TODO(abarth): Should this be a FlatButton?
new InkWell(
onTap: _handleSave,
child: new Text('SAVE')
)
)]
]
);
}

View File

@ -136,12 +136,13 @@ class MeasurementFragmentState extends State<MeasurementFragment> {
icon: "navigation/close",
onPressed: config.navigator.pop),
center: new Text('New Measurement'),
right: [new InkWell(
child: new GestureDetector(
right: [
// TODO(abarth): Should this be a FlatButton?
new InkWell(
onTap: _handleSave,
child: new Text('SAVE')
)
)]
]
);
}

View File

@ -55,52 +55,50 @@ class StockRow extends StatelessComponent {
String changeInPrice = "${stock.percentChange.toStringAsFixed(2)}%";
if (stock.percentChange > 0) changeInPrice = "+" + changeInPrice;
return new GestureDetector(
return new InkWell(
onTap: _getTapHandler(onPressed),
onLongPress: _getLongPressHandler(onLongPressed),
child: new InkWell(
child: new Container(
padding: const EdgeDims.TRBL(16.0, 16.0, 20.0, 16.0),
decoration: new BoxDecoration(
border: new Border(
bottom: new BorderSide(color: Theme.of(context).dividerColor)
)
child: new Container(
padding: const EdgeDims.TRBL(16.0, 16.0, 20.0, 16.0),
decoration: new BoxDecoration(
border: new Border(
bottom: new BorderSide(color: Theme.of(context).dividerColor)
)
),
child: new Row([
new Container(
key: arrowKey,
child: new StockArrow(percentChange: stock.percentChange),
margin: const EdgeDims.only(right: 5.0)
),
child: new Row([
new Container(
key: arrowKey,
child: new StockArrow(percentChange: stock.percentChange),
margin: const EdgeDims.only(right: 5.0)
),
new Flexible(
child: new Row([
new Flexible(
flex: 2,
child: new Text(
stock.symbol,
key: symbolKey
)
),
new Flexible(
child: new Text(
lastSale,
style: const TextStyle(textAlign: TextAlign.right),
key: priceKey
)
),
new Flexible(
child: new Text(
changeInPrice,
style: Theme.of(context).text.caption.copyWith(textAlign: TextAlign.right)
)
),
],
alignItems: FlexAlignItems.baseline,
textBaseline: DefaultTextStyle.of(context).textBaseline
)
new Flexible(
child: new Row([
new Flexible(
flex: 2,
child: new Text(
stock.symbol,
key: symbolKey
)
),
new Flexible(
child: new Text(
lastSale,
style: const TextStyle(textAlign: TextAlign.right),
key: priceKey
)
),
new Flexible(
child: new Text(
changeInPrice,
style: Theme.of(context).text.caption.copyWith(textAlign: TextAlign.right)
)
),
],
alignItems: FlexAlignItems.baseline,
textBaseline: DefaultTextStyle.of(context).textBaseline
)
])
)
)
])
)
);
}

View File

@ -14,11 +14,26 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
: super(router: router);
GestureTapCallback onTap;
GestureTapCallback onTapDown;
GestureTapCallback onTapCancel;
void handlePrimaryPointer(sky.PointerEvent event) {
if (event.type == 'pointerup') {
if (event.type == 'pointerdown') {
if (onTapDown != null)
onTapDown();
} else if (event.type == 'pointerup') {
resolve(GestureDisposition.accepted);
onTap();
if (onTap != null)
onTap();
}
}
void rejectGesture(int pointer) {
super.rejectGesture(pointer);
if (pointer == primaryPointer) {
assert(state == GestureRecognizerState.defunct);
if (onTapCancel != null)
onTapCancel();
}
}
}

View File

@ -51,7 +51,7 @@ abstract class RenderToggleable extends RenderConstrainedBox {
);
}
void detatch() {
void detach() {
_tap.dispose();
_tap = null;
super.detach();

View File

@ -375,22 +375,20 @@ class YearPickerState extends ScrollableWidgetListState<YearPicker> {
for(int i = start; i < start + count; i++) {
int year = config.firstDate.year + i;
String label = year.toString();
Widget item = new GestureDetector(
Widget item = new InkWell(
key: new Key(label),
onTap: () {
DateTime result = new DateTime(year, config.selectedDate.month, config.selectedDate.day);
config.onChanged(result);
},
child: new InkWell(
child: new Container(
height: config.itemExtent,
decoration: year == config.selectedDate.year ? new BoxDecoration(
backgroundColor: Theme.of(context).primarySwatch[100],
shape: Shape.circle
) : null,
child: new Center(
child: new Text(label, style: style)
)
child: new Container(
height: config.itemExtent,
decoration: year == config.selectedDate.year ? new BoxDecoration(
backgroundColor: Theme.of(context).primarySwatch[100],
shape: Shape.circle
) : null,
child: new Center(
child: new Text(label, style: style)
)
)
);

View File

@ -5,6 +5,7 @@
import 'dart:async';
import 'package:sky/animation.dart';
import 'package:sky/gestures.dart';
import 'package:sky/material.dart';
import 'package:sky/src/widgets/basic.dart';
import 'package:sky/src/widgets/focus.dart';
@ -52,7 +53,7 @@ class Dialog extends StatelessComponent {
final List<Widget> actions;
/// An (optional) callback that is called when the dialog is dismissed.
final Function onDismiss;
final GestureTapCallback onDismiss;
Color _getColor(BuildContext context) {
switch (Theme.of(context).brightness) {

View File

@ -10,7 +10,6 @@ import 'package:sky/painting.dart';
import 'package:sky/src/widgets/basic.dart';
import 'package:sky/src/widgets/button_state.dart';
import 'package:sky/src/widgets/framework.dart';
import 'package:sky/src/widgets/gesture_detector.dart';
import 'package:sky/src/widgets/icon.dart';
import 'package:sky/src/widgets/ink_well.dart';
import 'package:sky/src/widgets/theme.dart';
@ -76,14 +75,12 @@ class DrawerItemState extends ButtonState<DrawerItem> {
)
);
return new GestureDetector(
onTap: config.onPressed,
child: new Container(
height: 48.0,
decoration: new BoxDecoration(backgroundColor: _getBackgroundColor(themeData)),
child: new InkWell(
child: new Row(flexChildren)
)
return new Container(
height: 48.0,
decoration: new BoxDecoration(backgroundColor: _getBackgroundColor(themeData)),
child: new InkWell(
onTap: config.onPressed,
child: new Row(flexChildren)
)
);
}

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:sky/gestures.dart';
import 'package:sky/material.dart';
import 'package:sky/src/widgets/basic.dart';
import 'package:sky/src/widgets/framework.dart';
@ -13,7 +14,7 @@ class FlatButton extends MaterialButton {
Key key,
Widget child,
bool enabled: true,
Function onPressed
GestureTapCallback onPressed
}) : super(key: key,
child: child,
enabled: enabled,

View File

@ -6,7 +6,6 @@ import 'package:sky/gestures.dart';
import 'package:sky/src/widgets/basic.dart';
import 'package:sky/src/widgets/button_state.dart';
import 'package:sky/src/widgets/framework.dart';
import 'package:sky/src/widgets/gesture_detector.dart';
import 'package:sky/src/widgets/icon.dart';
import 'package:sky/src/widgets/ink_well.dart';
import 'package:sky/src/widgets/material.dart';
@ -46,17 +45,15 @@ class FloatingActionButtonState extends ButtonState<FloatingActionButton> {
type: MaterialType.circle,
level: highlight ? 3 : 2,
child: new ClipOval(
child: new GestureDetector(
onTap: config.onPressed,
child: new Container(
width: _kSize,
height: _kSize,
child: new InkWell(
child: new Center(
child: new IconTheme(
data: new IconThemeData(color: iconThemeColor),
child: config.child
)
child: new Container(
width: _kSize,
height: _kSize,
child: new InkWell(
onTap: config.onPressed,
child: new Center(
child: new IconTheme(
data: new IconThemeData(color: iconThemeColor),
child: config.child
)
)
)

View File

@ -14,6 +14,8 @@ class GestureDetector extends StatefulComponent {
Key key,
this.child,
this.onTap,
this.onTapDown,
this.onTapCancel,
this.onShowPress,
this.onLongPress,
this.onVerticalDragStart,
@ -33,6 +35,9 @@ class GestureDetector extends StatefulComponent {
final Widget child;
final GestureTapCallback onTap;
final GestureTapCallback onTapDown;
final GestureTapCallback onTapCancel;
final GestureShowPressCallback onShowPress;
final GestureLongPressCallback onLongPress;
@ -97,11 +102,14 @@ class GestureDetectorState extends State<GestureDetector> {
}
void _syncTap() {
if (config.onTap == null) {
if (config.onTap == null && config.onTapDown == null && config.onTapCancel == null) {
_tap = _ensureDisposed(_tap);
} else {
_tap ??= new TapGestureRecognizer(router: _router);
_tap.onTap = config.onTap;
_tap
..onTap = config.onTap
..onTapDown = config.onTapDown
..onTapCancel = config.onTapCancel;
}
}

View File

@ -4,6 +4,7 @@
import 'dart:sky' as sky;
import 'package:sky/gestures.dart';
import 'package:sky/src/widgets/basic.dart';
import 'package:sky/src/widgets/icon.dart';
import 'package:sky/src/widgets/framework.dart';
@ -13,8 +14,8 @@ class IconButton extends StatelessComponent {
const IconButton({ Key key, this.icon, this.onPressed, this.color }) : super(key: key);
final String icon;
final Function onPressed;
final Color color;
final GestureTapCallback onPressed;
Widget build(BuildContext context) {
Widget child = new Icon(type: icon, size: 24);

View File

@ -2,16 +2,18 @@
// 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:math' as math;
import 'dart:sky' as sky;
import 'package:sky/animation.dart';
import 'package:sky/gestures.dart';
import 'package:sky/rendering.dart';
import 'package:sky/src/widgets/basic.dart';
import 'package:sky/src/widgets/framework.dart';
const int _kSplashInitialOpacity = 0x30;
const double _kSplashCancelledVelocity = 0.7;
const double _kSplashCanceledVelocity = 0.7;
const double _kSplashConfirmedVelocity = 0.7;
const double _kSplashInitialSize = 0.0;
const double _kSplashUnconfirmedVelocity = 0.2;
@ -25,7 +27,7 @@ double _getSplashTargetSize(Size bounds, Point position) {
}
class InkSplash {
InkSplash(this.pointer, this.position, this.well) {
InkSplash(this.position, this.well) {
_targetRadius = _getSplashTargetSize(well.size, position);
_radius = new AnimatedValue<double>(
_kSplashInitialSize, end: _targetRadius, curve: easeOut);
@ -33,11 +35,12 @@ class InkSplash {
_performance = new ValueAnimation<double>(
variable: _radius,
duration: new Duration(milliseconds: (_targetRadius / _kSplashUnconfirmedVelocity).floor())
)..addListener(_handleRadiusChange)
..play();
)..addListener(_handleRadiusChange);
// Wait kTapTimeout to avoid creating tiny splashes during scrolls.
_startTimer = new Timer(kTapTimeout, _play);
}
final int pointer;
final Point position;
final RenderInkWell well;
@ -45,20 +48,39 @@ class InkSplash {
double _pinnedRadius;
AnimatedValue<double> _radius;
AnimationPerformance _performance;
Timer _startTimer;
bool _cancelStartTimer() {
if (_startTimer != null) {
_startTimer.cancel();
_startTimer = null;
return true;
}
return false;
}
void _play() {
_cancelStartTimer();
_performance.play();
}
void _updateVelocity(double velocity) {
int duration = (_targetRadius / velocity).floor();
_performance
..duration = new Duration(milliseconds: duration)
..play();
_performance.duration = new Duration(milliseconds: duration);
_play();
}
void confirm() {
if (_cancelStartTimer())
return;
_updateVelocity(_kSplashConfirmedVelocity);
_pinnedRadius = null;
}
void cancel() {
_updateVelocity(_kSplashCancelledVelocity);
if (_cancelStartTimer())
return;
_updateVelocity(_kSplashCanceledVelocity);
_pinnedRadius = _radius.value;
}
@ -77,38 +99,95 @@ class InkSplash {
}
class RenderInkWell extends RenderProxyBox {
RenderInkWell({ RenderBox child }) : super(child);
RenderInkWell({
RenderBox child,
GestureTapCallback onTap,
GestureLongPressCallback onLongPress
}) : super(child) {
this.onTap = onTap;
this.onLongPress = onLongPress;
}
GestureTapCallback get onTap => _onTap;
GestureTapCallback _onTap;
void set onTap (GestureTapCallback value) {
_onTap = value;
_syncTapRecognizer();
}
GestureTapCallback get onLongPress => _onLongPress;
GestureTapCallback _onLongPress;
void set onLongPress (GestureTapCallback value) {
_onLongPress = value;
_syncLongPressRecognizer();
}
final List<InkSplash> _splashes = new List<InkSplash>();
TapGestureRecognizer _tap;
LongPressGestureRecognizer _longPress;
void handleEvent(sky.Event event, BoxHitTestEntry entry) {
// TODO(abarth): We should trigger these effects based on gestures.
// https://github.com/flutter/engine/issues/1271
if (event is sky.PointerEvent) {
switch (event.type) {
case 'pointerdown':
_startSplash(event.pointer, entry.localPosition);
break;
case 'pointerup':
_confirmSplash(event.pointer);
break;
}
if (event.type == 'pointerdown' && (_tap != null || _longPress != null)) {
_tap?.addPointer(event);
_longPress?.addPointer(event);
_splashes.add(new InkSplash(entry.localPosition, this));
}
}
void _startSplash(int pointer, Point position) {
_splashes.add(new InkSplash(pointer, position, this));
markNeedsPaint();
void attach() {
super.attach();
_syncTapRecognizer();
_syncLongPressRecognizer();
}
void _forEachSplash(int pointer, Function callback) {
_splashes.where((splash) => splash.pointer == pointer)
.forEach(callback);
void detach() {
_disposeTapRecognizer();
_disposeLongPressRecognizer();
super.detach();
}
void _confirmSplash(int pointer) {
_forEachSplash(pointer, (splash) { splash.confirm(); });
markNeedsPaint();
void _syncTapRecognizer() {
if (onTap == null) {
_disposeTapRecognizer();
} else {
_tap ??= new TapGestureRecognizer(router: FlutterBinding.instance.pointerRouter)
..onTap = _handleTap
..onTapCancel = _handleTapCancel;
}
}
void _disposeTapRecognizer() {
_tap?.dispose();
_tap = null;
}
void _syncLongPressRecognizer() {
if (onLongPress == null) {
_disposeLongPressRecognizer();
} else {
_longPress ??= new LongPressGestureRecognizer(router: FlutterBinding.instance.pointerRouter)
..onLongPress = _handleLongPress;
}
}
void _disposeLongPressRecognizer() {
_longPress?.dispose();
_longPress = null;
}
void _handleTap() {
_splashes.last?.confirm();
onTap();
}
void _handleTapCancel() {
_splashes.last?.cancel();
}
void _handleLongPress() {
_splashes.last?.confirm();
onLongPress();
}
void paint(PaintingContext context, Offset offset) {
@ -126,7 +205,20 @@ class RenderInkWell extends RenderProxyBox {
}
class InkWell extends OneChildRenderObjectWidget {
InkWell({ Key key, Widget child }) : super(key: key, child: child);
InkWell({
Key key,
Widget child,
this.onTap,
this.onLongPress
}) : super(key: key, child: child);
RenderInkWell createRenderObject() => new RenderInkWell();
final GestureTapCallback onTap;
final GestureLongPressCallback onLongPress;
RenderInkWell createRenderObject() => new RenderInkWell(onTap: onTap, onLongPress: onLongPress);
void updateRenderObject(RenderInkWell renderObject, InkWell oldWidget) {
renderObject.onTap = onTap;
renderObject.onLongPress = onLongPress;
}
}

View File

@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:sky/gestures.dart';
import 'package:sky/src/widgets/basic.dart';
import 'package:sky/src/widgets/button_state.dart';
import 'package:sky/src/widgets/framework.dart';
import 'package:sky/src/widgets/gesture_detector.dart';
import 'package:sky/src/widgets/ink_well.dart';
import 'package:sky/src/widgets/material.dart';
@ -22,7 +22,7 @@ abstract class MaterialButton extends StatefulComponent {
final Widget child;
final bool enabled;
final Function onPressed;
final GestureTapCallback onPressed;
}
abstract class MaterialButtonState<T extends MaterialButton> extends ButtonState<T> {
@ -37,17 +37,17 @@ abstract class MaterialButtonState<T extends MaterialButton> extends ButtonState
child: config.child // TODO(ianh): figure out a way to compell the child to have gray text when disabled...
)
);
return new GestureDetector(
onTap: config.enabled ? config.onPressed : null,
child: new Container(
height: 36.0,
constraints: new BoxConstraints(minWidth: 88.0),
margin: new EdgeDims.all(8.0),
child: new Material(
type: MaterialType.button,
child: config.enabled ? new InkWell(child: contents) : contents,
level: level,
color: getColor(context)
return new Container(
height: 36.0,
constraints: new BoxConstraints(minWidth: 88.0),
margin: new EdgeDims.all(8.0),
child: new Material(
type: MaterialType.button,
level: level,
color: getColor(context),
child: new InkWell(
onTap: config.enabled ? config.onPressed : null,
child: contents
)
)
);

View File

@ -11,7 +11,7 @@ import 'package:sky/painting.dart';
import 'package:sky/src/widgets/basic.dart';
import 'package:sky/src/widgets/focus.dart';
import 'package:sky/src/widgets/framework.dart';
import 'package:sky/src/widgets/gesture_detector.dart';
import 'package:sky/src/widgets/ink_well.dart';
import 'package:sky/src/widgets/navigator.dart';
import 'package:sky/src/widgets/popup_menu_item.dart';
import 'package:sky/src/widgets/scrollable.dart';
@ -94,7 +94,7 @@ class PopupMenuState extends State<PopupMenu> {
children.add(new FadeTransition(
performance: config.performance,
opacity: new AnimatedValue<double>(0.0, end: 1.0, interval: new Interval(start, end)),
child: new GestureDetector(
child: new InkWell(
onTap: () { config.navigator.pop(config.items[i].value); },
child: config.items[i]
))

View File

@ -4,7 +4,6 @@
import 'package:sky/src/widgets/basic.dart';
import 'package:sky/src/widgets/framework.dart';
import 'package:sky/src/widgets/ink_well.dart';
import 'package:sky/src/widgets/theme.dart';
const double _kMenuItemHeight = 48.0;
@ -21,15 +20,13 @@ class PopupMenuItem extends StatelessComponent {
final dynamic value;
Widget build(BuildContext context) {
return new InkWell(
child: new Container(
height: _kMenuItemHeight,
child: new DefaultTextStyle(
style: Theme.of(context).text.subhead,
child: new Baseline(
baseline: _kMenuItemHeight - _kBaselineOffsetFromBottom,
child: child
)
return new Container(
height: _kMenuItemHeight,
child: new DefaultTextStyle(
style: Theme.of(context).text.subhead,
child: new Baseline(
baseline: _kMenuItemHeight - _kBaselineOffsetFromBottom,
child: child
)
)
);

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:sky/gestures.dart';
import 'package:sky/material.dart';
import 'package:sky/src/widgets/basic.dart';
import 'package:sky/src/widgets/framework.dart';
@ -13,7 +14,7 @@ class RaisedButton extends MaterialButton {
Key key,
Widget child,
bool enabled: true,
Function onPressed
GestureTapCallback onPressed
}) : super(key: key,
child: child,
enabled: enabled,

View File

@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:sky/animation.dart';
import 'package:sky/painting.dart';
import 'package:sky/gestures.dart';
import 'package:sky/material.dart';
import 'package:sky/painting.dart';
import 'package:sky/src/widgets/animated_component.dart';
import 'package:sky/src/widgets/basic.dart';
import 'package:sky/src/widgets/framework.dart';
@ -28,7 +28,7 @@ class SnackBarAction extends StatelessComponent {
}
final String label;
final Function onPressed;
final GestureTapCallback onPressed;
Widget build(BuildContext) {
return new GestureDetector(

View File

@ -7,9 +7,10 @@ import 'dart:sky' as sky;
import 'package:newton/newton.dart';
import 'package:sky/animation.dart';
import 'package:sky/gestures.dart';
import 'package:sky/material.dart';
import 'package:sky/painting.dart';
import 'package:sky/rendering.dart';
import 'package:sky/material.dart';
import 'package:sky/src/widgets/basic.dart';
import 'package:sky/src/widgets/framework.dart';
import 'package:sky/src/widgets/gesture_detector.dart';
@ -307,6 +308,7 @@ class TabLabel {
class Tab extends StatelessComponent {
Tab({
Key key,
this.onSelected,
this.label,
this.color,
this.selected: false,
@ -315,6 +317,7 @@ class Tab extends StatelessComponent {
assert(label.text != null || label.icon != null);
}
final GestureTapCallback onSelected;
final TabLabel label;
final Color color;
final bool selected;
@ -359,7 +362,10 @@ class Tab extends StatelessComponent {
padding: _kTabLabelPadding
);
return new InkWell(child: centeredLabel);
return new InkWell(
onTap: onSelected,
child: centeredLabel
);
}
}
@ -458,7 +464,7 @@ class TabBarState extends ScrollableState<TabBar> {
.clamp(scrollBehavior.minScrollOffset, scrollBehavior.maxScrollOffset);
}
void _handleTap(int tabIndex) {
void _handleTabSelected(int tabIndex) {
if (tabIndex != config.selectedIndex) {
if (_tabWidths != null) {
if (config.isScrollable)
@ -471,14 +477,12 @@ class TabBarState extends ScrollableState<TabBar> {
}
Widget _toTab(TabLabel label, int tabIndex, Color color, Color selectedColor) {
return new GestureDetector(
onTap: () => _handleTap(tabIndex),
child: new Tab(
label: label,
color: color,
selected: tabIndex == config.selectedIndex,
selectedColor: selectedColor
)
return new Tab(
onSelected: () => _handleTabSelected(tabIndex),
label: label,
color: color,
selected: tabIndex == config.selectedIndex,
selectedColor: selectedColor
);
}