private static int GetSystemResourceDimenPx(AccessibilityService service, string resName) { var resourceId = service.Resources.GetIdentifier(resName, "dimen", "android"); if (resourceId > 0) { return(service.Resources.GetDimensionPixelSize(resourceId)); } return(0); }
public static Point GetOverlayAnchorPosition(AccessibilityService service, AccessibilityNodeInfo anchorView, int overlayViewHeight, bool isOverlayAboveAnchor) { var anchorViewRect = new Rect(); anchorView.GetBoundsInScreen(anchorViewRect); var anchorViewX = anchorViewRect.Left; var anchorViewY = isOverlayAboveAnchor ? anchorViewRect.Top : anchorViewRect.Bottom; anchorViewRect.Dispose(); if (isOverlayAboveAnchor) { anchorViewY -= overlayViewHeight; } anchorViewY -= GetStatusBarHeight(service); return(new Point(anchorViewX, anchorViewY)); }
private static int GetNavigationBarHeight(AccessibilityService service) { return(GetSystemResourceDimenPx(service, "navigation_bar_height")); }
private static int GetStatusBarHeight(AccessibilityService service) { return(GetSystemResourceDimenPx(service, "status_bar_height")); }
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); }