コード例 #1
0
        public override void invoke(FocusNode node, Intent intent)
        {
            ScrollableState state = Scrollable.of(node.context);

            D.assert(state != null, () => "ScrollAction was invoked on a context that has no scrollable parent");
            D.assert(state.position.havePixels, () => "Scrollable must be laid out before it can be scrolled via a ScrollAction");
            if (state.widget.physics != null && !state.widget.physics.shouldAcceptUserOffset(state.position))
            {
                return;
            }
            float increment = _getIncrement(state, intent as ScrollIntent);

            if (increment == 0.0f)
            {
                return;
            }
            state.position.moveTo(
                state.position.pixels + increment,
                duration: TimeSpan.FromMilliseconds(100),
                curve: Curves.easeInOut
                );
        }
コード例 #2
0
        public override bool inDirection(FocusNode currentNode, TraversalDirection direction)
        {
            FocusScopeNode nearestScope = currentNode.nearestScope;
            FocusNode      focusedChild = nearestScope.focusedChild;

            if (focusedChild == null)
            {
                FocusNode firstFocus = findFirstFocusInDirection(currentNode, direction) ?? currentNode;
                switch (direction)
                {
                case TraversalDirection.up:
                case TraversalDirection.left:
                    FocusTravesalUtils._focusAndEnsureVisible(
                        firstFocus,
                        alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtStart
                        );
                    break;

                case TraversalDirection.right:
                case TraversalDirection.down:
                    FocusTravesalUtils._focusAndEnsureVisible(
                        firstFocus,
                        alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtEnd
                        );
                    break;
                }
                return(true);
            }
            if (_popPolicyDataIfNeeded(direction, nearestScope, focusedChild))
            {
                return(true);
            }
            FocusNode       found             = null;
            ScrollableState focusedScrollable = Scrollable.of(focusedChild.context);

            switch (direction)
            {
            case TraversalDirection.down:
            case TraversalDirection.up:
                IEnumerable <FocusNode> eligibleNodes = _sortAndFilterVertically(
                    direction,
                    focusedChild.rect,
                    nearestScope.traversalDescendants
                    );
                if (focusedScrollable != null && !focusedScrollable.position.atEdge())
                {
                    IEnumerable <FocusNode> filteredEligibleNodes = LinqUtils <FocusNode> .WhereList(eligibleNodes, ((FocusNode node) => Scrollable.of(node.context) == focusedScrollable));

                    if (filteredEligibleNodes.Count() != 0)
                    {
                        eligibleNodes = filteredEligibleNodes;
                    }
                }
                if (eligibleNodes.Count() == 0)
                {
                    break;
                }
                List <FocusNode> sorted = eligibleNodes.ToList();
                if (direction == TraversalDirection.up)
                {
                    //sorted = sorted.reversed.toList();
                    sorted.Reverse();
                    sorted = sorted.ToList();
                }
                Rect band = Rect.fromLTRB(focusedChild.rect.left, float.NegativeInfinity, focusedChild.rect.right, float.PositiveInfinity);
                IEnumerable <FocusNode> inBand = LinqUtils <FocusNode> .WhereList(sorted, ((FocusNode node) => !node.rect.intersect(band).isEmpty));

                if (inBand.Count() != 0)
                {
                    found = inBand.First();
                    break;
                }
                FocusTravesalUtils.mergeSort <FocusNode>(sorted, compare: (FocusNode a, FocusNode b) => {
                    return((a.rect.center.dx - focusedChild.rect.center.dx).abs().CompareTo((b.rect.center.dx - focusedChild.rect.center.dx).abs()));
                });
                found = sorted.First();
                break;

            case TraversalDirection.right:
            case TraversalDirection.left:
                eligibleNodes = _sortAndFilterHorizontally(direction, focusedChild.rect, nearestScope);
                if (focusedScrollable != null && !focusedScrollable.position.atEdge())
                {
                    IEnumerable <FocusNode> filteredEligibleNodes = LinqUtils <FocusNode> .WhereList(eligibleNodes, ((FocusNode node) => Scrollable.of(node.context) == focusedScrollable));

                    if (filteredEligibleNodes.Count() != 0)
                    {
                        eligibleNodes = filteredEligibleNodes;
                    }
                }
                if (eligibleNodes.Count() == 0)
                {
                    break;
                }
                sorted = eligibleNodes.ToList();
                if (direction == TraversalDirection.left)
                {
                    sorted.Reverse();
                    sorted = sorted.ToList();
                    //sorted = sorted.reversed.toList();
                }
                band   = Rect.fromLTRB(float.NegativeInfinity, focusedChild.rect.top, float.PositiveInfinity, focusedChild.rect.bottom);
                inBand = LinqUtils <FocusNode> .WhereList(sorted, ((FocusNode node) => !node.rect.intersect(band).isEmpty));

                if (inBand.Count() != 0)
                {
                    found = inBand.First();
                    break;
                }
                FocusTravesalUtils.mergeSort <FocusNode>(sorted, compare: (FocusNode a, FocusNode b) => {
                    return((a.rect.center.dy - focusedChild.rect.center.dy).abs().CompareTo((b.rect.center.dy - focusedChild.rect.center.dy).abs()));
                });
                found = sorted.First();
                break;
            }
            if (found != null)
            {
                _pushPolicyData(direction, nearestScope, focusedChild);
                switch (direction)
                {
                case TraversalDirection.up:
                case TraversalDirection.left:
                    FocusTravesalUtils._focusAndEnsureVisible(
                        found,
                        alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtStart
                        );
                    break;

                case TraversalDirection.down:
                case TraversalDirection.right:
                    FocusTravesalUtils._focusAndEnsureVisible(
                        found,
                        alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtEnd
                        );
                    break;
                }
                return(true);
            }
            return(false);
        }
コード例 #3
0
 public override bool isEnabled(BuildContext context)
 {
     return(Scrollable.of(context) != null);
 }
コード例 #4
0
        public bool _popPolicyDataIfNeeded(TraversalDirection direction, FocusScopeNode nearestScope, FocusNode focusedChild)
        {
            _DirectionalPolicyData policyData = _policyData[nearestScope];

            if (policyData != null && policyData.history.isNotEmpty() && policyData.history.First().direction != direction)
            {
                if (policyData.history.Last().node.parent == null)
                {
                    invalidateScopeData(nearestScope);
                    return(false);
                }
                bool popOrInvalidate(TraversalDirection _direction)
                {
                    FocusNode lastNode = policyData.history.removeLast().node;

                    if (Scrollable.of(lastNode.context) != Scrollable.of(FocusManagerUtils.primaryFocus.context))
                    {
                        invalidateScopeData(nearestScope);
                        return(false);
                    }
                    ScrollPositionAlignmentPolicy alignmentPolicy = ScrollPositionAlignmentPolicy.explicitPolicy;

                    switch (_direction)
                    {
                    case TraversalDirection.up:
                    case TraversalDirection.left:
                        alignmentPolicy = ScrollPositionAlignmentPolicy.keepVisibleAtStart;
                        break;

                    case TraversalDirection.right:
                    case TraversalDirection.down:
                        alignmentPolicy = ScrollPositionAlignmentPolicy.keepVisibleAtEnd;
                        break;
                    }
                    FocusTravesalUtils._focusAndEnsureVisible(
                        lastNode,
                        alignmentPolicy: alignmentPolicy
                        );
                    return(true);
                }

                switch (direction)
                {
                case TraversalDirection.down:
                case TraversalDirection.up:
                    switch (policyData.history.First().direction)
                    {
                    case TraversalDirection.left:
                    case TraversalDirection.right:
                        invalidateScopeData(nearestScope);
                        break;

                    case TraversalDirection.up:
                    case TraversalDirection.down:
                        if (popOrInvalidate(direction))
                        {
                            return(true);
                        }
                        break;
                    }
                    break;

                case TraversalDirection.left:
                case TraversalDirection.right:
                    switch (policyData.history.First().direction)
                    {
                    case TraversalDirection.left:
                    case TraversalDirection.right:
                        if (popOrInvalidate(direction))
                        {
                            return(true);
                        }
                        break;

                    case TraversalDirection.up:
                    case TraversalDirection.down:
                        invalidateScopeData(nearestScope);
                        break;
                    }
                    break;
                }
            }
            if (policyData != null && policyData.history.isEmpty())
            {
                invalidateScopeData(nearestScope);
            }
            return(false);
        }