public static Point GetOverlayAnchorPosition(AccessibilityNodeInfo anchorNode, AccessibilityNodeInfo root,
                                                     IEnumerable <AccessibilityWindowInfo> windows)
        {
            Point point = null;

            if (anchorNode != null)
            {
                // Update node's info since this is still a reference from an older event
                anchorNode.Refresh();
                if (!anchorNode.VisibleToUser)
                {
                    return(new Point(-1, -1));
                }
                if (!anchorNode.Focused)
                {
                    return(null);
                }

                // node.VisibleToUser doesn't always give us exactly what we want, so attempt to tighten up the range
                // of visibility
                var rootNodeHeight = GetNodeHeight(root);
                var limitLowY      = 0;
                var limitHighY     = rootNodeHeight - GetNodeHeight(anchorNode);
                if (windows != null)
                {
                    if (IsStatusBarExpanded(windows))
                    {
                        return(new Point(-1, -1));
                    }
                    var inputWindowRect = GetInputMethodWindowRect(windows);
                    if (inputWindowRect != null)
                    {
                        limitLowY += inputWindowRect.Height();
                        if (Build.VERSION.SdkInt >= BuildVersionCodes.Q)
                        {
                            limitLowY += GetNavigationBarHeight() + GetStatusBarHeight();
                        }
                        inputWindowRect.Dispose();
                    }
                }

                point = GetOverlayAnchorPosition(root, anchorNode, rootNodeHeight);
                if (point.Y < limitLowY || point.Y > limitHighY)
                {
                    point.X = -1;
                    point.Y = -1;
                }
            }
            return(point);
        }
Пример #2
0
        public static Point GetOverlayAnchorPosition(AccessibilityService service, AccessibilityNodeInfo anchorNode,
                                                     AccessibilityNodeInfo root, IEnumerable <AccessibilityWindowInfo> windows, int overlayViewHeight,
                                                     bool isOverlayAboveAnchor)
        {
            Point point = null;

            if (anchorNode != null)
            {
                // Update node's info since this is still a reference from an older event
                anchorNode.Refresh();
                if (!anchorNode.VisibleToUser)
                {
                    return(new Point(-1, -1));
                }
                if (!anchorNode.Focused)
                {
                    return(null);
                }

                // node.VisibleToUser doesn't always give us exactly what we want, so attempt to tighten up the range
                // of visibility
                var inputMethodHeight = 0;
                if (windows != null)
                {
                    if (IsStatusBarExpanded(windows))
                    {
                        return(new Point(-1, -1));
                    }
                    inputMethodHeight = GetInputMethodHeight(windows);
                }
                var minY           = 0;
                var rootNodeHeight = GetNodeHeight(root);
                if (rootNodeHeight == -1)
                {
                    return(null);
                }
                var maxY = rootNodeHeight - GetNavigationBarHeight(service) - GetStatusBarHeight(service) -
                           inputMethodHeight;

                point = GetOverlayAnchorPosition(service, anchorNode, overlayViewHeight, isOverlayAboveAnchor);
                if (point.Y < minY)
                {
                    if (isOverlayAboveAnchor)
                    {
                        // view nearing bounds, anchor to bottom
                        point.X = -1;
                        point.Y = 0;
                    }
                    else
                    {
                        // view out of bounds, hide overlay
                        point.X = -1;
                        point.Y = -1;
                    }
                }
                else if (point.Y > (maxY - overlayViewHeight))
                {
                    if (isOverlayAboveAnchor)
                    {
                        // view out of bounds, hide overlay
                        point.X = -1;
                        point.Y = -1;
                    }
                    else
                    {
                        // view nearing bounds, anchor to top
                        point.X = 0;
                        point.Y = -1;
                    }
                }
                else if (isOverlayAboveAnchor && point.Y < (maxY - (overlayViewHeight * 2) - GetNodeHeight(anchorNode)))
                {
                    // This else block forces the overlay to return to bottom alignment as soon as space is available
                    // below the anchor view. Removing this will change the behavior to wait until there isn't enough
                    // space above the anchor view before returning to bottom alignment.
                    point.X = -1;
                    point.Y = 0;
                }
            }
            return(point);
        }