Add ensureWidgetIsVisible to fn3
This commit is contained in:
parent
d717be946a
commit
3387bbaa37
@ -396,6 +396,8 @@ typedef void ElementVisitor(Element element);
|
||||
abstract class BuildContext {
|
||||
InheritedWidget inheritedWidgetOfType(Type targetType);
|
||||
RenderObject findRenderObject();
|
||||
|
||||
void visitAncestorElements(bool visitor(Element element));
|
||||
}
|
||||
|
||||
/// Elements are the instantiations of Widget configurations.
|
||||
@ -607,6 +609,12 @@ abstract class Element<T extends Widget> implements BuildContext {
|
||||
|
||||
RenderObject findRenderObject() => renderObject;
|
||||
|
||||
void visitAncestorElements(bool visitor(Element element)) {
|
||||
Element ancestor = _parent;
|
||||
while (ancestor != null && visitor(ancestor))
|
||||
ancestor = ancestor._parent;
|
||||
}
|
||||
|
||||
void dependenciesChanged() {
|
||||
assert(false);
|
||||
}
|
||||
|
@ -207,8 +207,62 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(abarth): findScrollableAncestor
|
||||
// TODO(abarth): ensureWidgetIsVisible
|
||||
ScrollableState findScrollableAncestor(BuildContext context) {
|
||||
ScrollableState result;
|
||||
context.visitAncestorElements((Element element) {
|
||||
if (element is StatefulComponentElement) {
|
||||
if (element.state is ScrollableState) {
|
||||
result = element.state;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
Future ensureWidgetIsVisible(BuildContext context, { Duration duration, Curve curve }) {
|
||||
assert(context.findRenderObject() is RenderBox);
|
||||
// TODO(abarth): This function doesn't handle nested scrollable widgets.
|
||||
|
||||
ScrollableState scrollable = findScrollableAncestor(context);
|
||||
if (scrollable == null)
|
||||
return new Future.value();
|
||||
|
||||
RenderBox targetBox = context.findRenderObject();
|
||||
assert(targetBox.attached);
|
||||
Size targetSize = targetBox.size;
|
||||
|
||||
RenderBox scrollableBox = scrollable.context.findRenderObject();
|
||||
assert(scrollableBox.attached);
|
||||
Size scrollableSize = scrollableBox.size;
|
||||
|
||||
double scrollOffsetDelta;
|
||||
switch (scrollable.config.scrollDirection) {
|
||||
case ScrollDirection.vertical:
|
||||
Point targetCenter = targetBox.localToGlobal(new Point(0.0, targetSize.height / 2.0));
|
||||
Point scrollableCenter = scrollableBox.localToGlobal(new Point(0.0, scrollableSize.height / 2.0));
|
||||
scrollOffsetDelta = targetCenter.y - scrollableCenter.y;
|
||||
break;
|
||||
case ScrollDirection.horizontal:
|
||||
Point targetCenter = targetBox.localToGlobal(new Point(targetSize.width / 2.0, 0.0));
|
||||
Point scrollableCenter = scrollableBox.localToGlobal(new Point(scrollableSize.width / 2.0, 0.0));
|
||||
scrollOffsetDelta = targetCenter.x - scrollableCenter.x;
|
||||
break;
|
||||
case ScrollDirection.both:
|
||||
assert(false); // See https://github.com/flutter/engine/issues/888
|
||||
break;
|
||||
}
|
||||
|
||||
ExtentScrollBehavior scrollBehavior = scrollable.scrollBehavior;
|
||||
double scrollOffset = (scrollable.scrollOffset + scrollOffsetDelta)
|
||||
.clamp(scrollBehavior.minScrollOffset, scrollBehavior.maxScrollOffset);
|
||||
|
||||
if (scrollOffset != scrollable.scrollOffset)
|
||||
return scrollable.scrollTo(scrollOffset, duration: duration, curve: curve);
|
||||
|
||||
return new Future.value();
|
||||
}
|
||||
|
||||
/// A simple scrollable widget that has a single child. Use this component if
|
||||
/// you are not worried about offscreen widgets consuming resources.
|
||||
|
Loading…
x
Reference in New Issue
Block a user