|
|
|
|
|
|
using UnityEngine; |
|
|
|
|
|
|
|
namespace Unity.UIWidgets.widgets { |
|
|
|
public enum ScrollViewKeyboardDismissBehavior { |
|
|
|
manual, |
|
|
|
onDrag |
|
|
|
} |
|
|
|
|
|
|
|
public abstract class ScrollView : StatelessWidget { |
|
|
|
protected ScrollView( |
|
|
|
Key key = null, |
|
|
|
|
|
|
Key center = null, |
|
|
|
float anchor = 0.0f, |
|
|
|
float? cacheExtent = null, |
|
|
|
DragStartBehavior dragStartBehavior = DragStartBehavior.start |
|
|
|
DragStartBehavior dragStartBehavior = DragStartBehavior.start, |
|
|
|
ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual |
|
|
|
) : base(key: key) { |
|
|
|
D.assert(!(controller != null && primary == true), |
|
|
|
() => "Primary ScrollViews obtain their ScrollController via inheritance from a PrimaryScrollController widget. " + |
|
|
|
|
|
|
this.anchor = anchor; |
|
|
|
this.cacheExtent = cacheExtent; |
|
|
|
this.dragStartBehavior = dragStartBehavior; |
|
|
|
this.keyboardDismissBehavior = keyboardDismissBehavior; |
|
|
|
} |
|
|
|
|
|
|
|
public readonly Axis scrollDirection; |
|
|
|
|
|
|
public readonly float anchor; |
|
|
|
public readonly float? cacheExtent; |
|
|
|
public readonly DragStartBehavior dragStartBehavior; |
|
|
|
public readonly ScrollViewKeyboardDismissBehavior keyboardDismissBehavior; |
|
|
|
|
|
|
|
protected AxisDirection getDirection(BuildContext context) { |
|
|
|
return LayoutUtils.getAxisDirectionFromAxisReverseAndDirectionality( |
|
|
|
|
|
|
viewportBuilder: (viewportContext, offset) => |
|
|
|
buildViewport(viewportContext, offset, axisDirection, slivers) |
|
|
|
); |
|
|
|
return primary && scrollController != null |
|
|
|
|
|
|
|
Widget scrollableResult = primary && scrollController != null |
|
|
|
|
|
|
|
if (keyboardDismissBehavior == ScrollViewKeyboardDismissBehavior.onDrag) { |
|
|
|
return new NotificationListener<ScrollUpdateNotification>( |
|
|
|
child: scrollableResult, |
|
|
|
onNotification: (ScrollUpdateNotification notification) => { |
|
|
|
FocusScopeNode focusScope = FocusScope.of(context); |
|
|
|
if (notification.dragDetails != null && focusScope.hasFocus) { |
|
|
|
focusScope.unfocus(); |
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
); |
|
|
|
} |
|
|
|
else { |
|
|
|
return scrollableResult; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
|
|
|
|
|
|
bool shrinkWrap = false, |
|
|
|
EdgeInsets padding = null, |
|
|
|
float? cacheExtent = null, |
|
|
|
DragStartBehavior dragStartBehavior = DragStartBehavior.start |
|
|
|
DragStartBehavior dragStartBehavior = DragStartBehavior.start, |
|
|
|
ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual |
|
|
|
) : base( |
|
|
|
key: key, |
|
|
|
scrollDirection: scrollDirection, |
|
|
|
|
|
|
physics: physics, |
|
|
|
shrinkWrap: shrinkWrap, |
|
|
|
cacheExtent: cacheExtent, |
|
|
|
dragStartBehavior: dragStartBehavior |
|
|
|
dragStartBehavior: dragStartBehavior, |
|
|
|
keyboardDismissBehavior: keyboardDismissBehavior |
|
|
|
) { |
|
|
|
this.padding = padding; |
|
|
|
} |
|
|
|
|
|
|
bool addRepaintBoundaries = true, |
|
|
|
float? cacheExtent = null, |
|
|
|
List<Widget> children = null, |
|
|
|
DragStartBehavior dragStartBehavior = DragStartBehavior.start |
|
|
|
DragStartBehavior dragStartBehavior = DragStartBehavior.start, |
|
|
|
ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual |
|
|
|
) : base( |
|
|
|
key: key, |
|
|
|
scrollDirection: scrollDirection, |
|
|
|
|
|
|
shrinkWrap: shrinkWrap, |
|
|
|
padding: padding, |
|
|
|
cacheExtent: cacheExtent, |
|
|
|
dragStartBehavior: dragStartBehavior |
|
|
|
dragStartBehavior: dragStartBehavior, |
|
|
|
keyboardDismissBehavior: keyboardDismissBehavior |
|
|
|
) { |
|
|
|
this.itemExtent = itemExtent; |
|
|
|
childrenDelegate = new SliverChildListDelegate( |
|
|
|
|
|
|
bool addAutomaticKeepAlives = true, |
|
|
|
bool addRepaintBoundaries = true, |
|
|
|
float? cacheExtent = null, |
|
|
|
DragStartBehavior dragStartBehavior = DragStartBehavior.start |
|
|
|
DragStartBehavior dragStartBehavior = DragStartBehavior.start, |
|
|
|
ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual |
|
|
|
) : base(key: key, |
|
|
|
scrollDirection: scrollDirection, |
|
|
|
reverse: reverse, |
|
|
|
|
|
|
shrinkWrap: shrinkWrap, |
|
|
|
padding: padding, |
|
|
|
cacheExtent: cacheExtent, |
|
|
|
dragStartBehavior: dragStartBehavior |
|
|
|
dragStartBehavior: dragStartBehavior, |
|
|
|
keyboardDismissBehavior: keyboardDismissBehavior |
|
|
|
D.assert(itemCount == null || itemCount >= 0); |
|
|
|
this.itemExtent = itemExtent; |
|
|
|
childrenDelegate = new SliverChildBuilderDelegate( |
|
|
|
itemBuilder, |
|
|
|
|
|
|
bool addAutomaticKeepAlives = true, |
|
|
|
bool addRepaintBoundaries = true, |
|
|
|
float? cacheExtent = null, |
|
|
|
DragStartBehavior dragStartBehavior = DragStartBehavior.start |
|
|
|
DragStartBehavior dragStartBehavior = DragStartBehavior.start, |
|
|
|
ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual |
|
|
|
) { |
|
|
|
return new ListView( |
|
|
|
key: key, |
|
|
|
|
|
|
itemCount: itemCount, |
|
|
|
addAutomaticKeepAlives: addAutomaticKeepAlives, |
|
|
|
addRepaintBoundaries: addRepaintBoundaries, |
|
|
|
dragStartBehavior: dragStartBehavior |
|
|
|
dragStartBehavior: dragStartBehavior, |
|
|
|
keyboardDismissBehavior: keyboardDismissBehavior |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
bool addAutomaticKeepAlives = true, |
|
|
|
bool addRepaintBoundaries = true, |
|
|
|
float? cacheExtent = null, |
|
|
|
DragStartBehavior dragStartBehavior = DragStartBehavior.start |
|
|
|
DragStartBehavior dragStartBehavior = DragStartBehavior.start, |
|
|
|
ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual |
|
|
|
) : base( |
|
|
|
key: key, |
|
|
|
scrollDirection: scrollDirection, |
|
|
|
|
|
|
shrinkWrap: shrinkWrap, |
|
|
|
padding: padding, |
|
|
|
cacheExtent: cacheExtent, |
|
|
|
dragStartBehavior: dragStartBehavior |
|
|
|
dragStartBehavior: dragStartBehavior, |
|
|
|
keyboardDismissBehavior: keyboardDismissBehavior |
|
|
|
) { |
|
|
|
D.assert(itemBuilder != null); |
|
|
|
D.assert(separatorBuilder != null); |
|
|
|
|
|
|
(context, index) => { |
|
|
|
int itemIndex = index / 2; |
|
|
|
return index % 2 == 0 |
|
|
|
? itemBuilder(context, itemIndex) |
|
|
|
: separatorBuilder(context, itemIndex); |
|
|
|
Widget widget = null; |
|
|
|
if (index % 2 == 0) { |
|
|
|
widget = itemBuilder(context, itemIndex); |
|
|
|
} |
|
|
|
else { |
|
|
|
widget = separatorBuilder(context, itemIndex); |
|
|
|
D.assert(() => { |
|
|
|
if (widget == null) { |
|
|
|
throw new UIWidgetsError("separatorBuilder cannot return null."); |
|
|
|
} |
|
|
|
|
|
|
|
return true; |
|
|
|
}); |
|
|
|
} |
|
|
|
return widget; |
|
|
|
childCount: Mathf.Max(0, itemCount * 2 - 1), |
|
|
|
childCount: _computeActualChildCount(itemCount), |
|
|
|
addAutomaticKeepAlives: addAutomaticKeepAlives, |
|
|
|
addRepaintBoundaries: addRepaintBoundaries |
|
|
|
); |
|
|
|
|
|
|
int itemCount = 0, |
|
|
|
bool addAutomaticKeepAlives = true, |
|
|
|
bool addRepaintBoundaries = true, |
|
|
|
float? cacheExtent = null |
|
|
|
float? cacheExtent = null, |
|
|
|
ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual |
|
|
|
) { |
|
|
|
return new ListView( |
|
|
|
key, |
|
|
|
|
|
|
itemCount, |
|
|
|
addAutomaticKeepAlives, |
|
|
|
addRepaintBoundaries, |
|
|
|
cacheExtent |
|
|
|
cacheExtent, |
|
|
|
keyboardDismissBehavior: keyboardDismissBehavior |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
base.debugFillProperties(properties); |
|
|
|
properties.add(new FloatProperty("itemExtent", itemExtent, |
|
|
|
defaultValue: foundation_.kNullDefaultValue)); |
|
|
|
} |
|
|
|
|
|
|
|
static int _computeActualChildCount(int itemCount) { |
|
|
|
return Mathf.Max(0, itemCount * 2 - 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|