Line data Source code
1 : import 'package:flutter/foundation.dart'; 2 : import 'package:flutter/material.dart'; 3 : import 'package:flutter_ume/flutter_ume.dart'; 4 : 5 : class HitTest { 6 : // all of RenderObjects of current point 7 3 : static List<RenderObject> hitTest( 8 : Offset? position, { 9 : double edgeHitMargin = 0.0, 10 : }) { 11 9 : final dynamic ignorePointer = rootKey.currentContext!.findRenderObject(); 12 3 : final RenderObject userRender = ignorePointer.child; 13 : 14 3 : bool _hitTestHelper( 15 : List<RenderObject> hits, 16 : List<RenderObject> edgeHits, 17 : Offset? position, 18 : RenderObject object, 19 : Matrix4 transform, 20 : ) { 21 : bool hit = false; 22 3 : final Matrix4? inverse = Matrix4.tryInvert(transform); 23 : if (inverse == null) { 24 : return false; 25 : } 26 : final Offset localPosition = 27 3 : MatrixUtils.transformPoint(inverse, position!); 28 : 29 3 : final List<DiagnosticsNode> children = object.debugDescribeChildren(); 30 12 : for (int i = children.length - 1; i >= 0; i -= 1) { 31 3 : final DiagnosticsNode diagnostics = children[i]; 32 0 : assert(diagnostics != null); 33 6 : if (diagnostics.style == DiagnosticsTreeStyle.offstage || 34 6 : diagnostics.value is! RenderObject) continue; 35 3 : final RenderObject child = diagnostics.value as RenderObject; 36 3 : final Rect? paintClip = object.describeApproximatePaintClip(child); 37 3 : if (paintClip != null && !paintClip.contains(localPosition)) continue; 38 : 39 3 : final Matrix4 childTransform = transform.clone(); 40 3 : object.applyPaintTransform(child, childTransform); 41 3 : if (_hitTestHelper(hits, edgeHits, position, child, childTransform)) 42 : hit = true; 43 : } 44 : 45 3 : final Rect bounds = object.semanticBounds; 46 3 : if (bounds.contains(localPosition)) { 47 : hit = true; 48 6 : if (!bounds.deflate(edgeHitMargin).contains(localPosition)) 49 0 : edgeHits.add(object); 50 : } 51 3 : if (hit) hits.add(object); 52 : return hit; 53 : } 54 : 55 3 : final List<RenderObject> regularHits = <RenderObject>[]; 56 3 : final List<RenderObject> edgeHits = <RenderObject>[]; 57 : 58 3 : _hitTestHelper(regularHits, edgeHits, position, userRender, 59 3 : userRender.getTransformTo(null)); 60 3 : double _area(RenderObject object) { 61 6 : final Size size = object.semanticBounds.size; 62 9 : return size.width * size.height; 63 : } 64 : 65 : regularHits 66 15 : .sort((RenderObject a, RenderObject b) => _area(a).compareTo(_area(b))); 67 : final Set<RenderObject> hits = Set<RenderObject>(); 68 3 : hits.addAll(edgeHits); 69 3 : hits.addAll(regularHits); 70 3 : return hits.toList(); 71 : } 72 : }