Get frame from specific UISegmentedControl index?

In my application, I use UIPopoverController and I use the presentPopoverFromRect API. What I'm doing right now just sets it into the frame of my entire UISegmentedControl. However, I want to be more precise than that. Is there a way to get a frame of a specific index in a UISegmentedControl?

Thanks!

+4
source share
4 answers

If the segments are equal, why not just divide the width of the control by the number of the selected segment (+1, because the numbering starts at 0)? EDIT: Like this one

 -(void)showPopover:(id)sender { if ((UISegmentedControl*)sender.selectedSegmentIndex == 0) [self.popover presentPopoverFromRect:CGRectMake(self.segmentedControl.frame.size.width/6, self.segmentedControl.frame.origin.y, aWidth, aHeight)] } 

This is more than 6 (I assume an implementation of 3 segments), because you need to get the center of the segment, and 3 - put it on the line. And if you do some simple math here (let's say that the entire control is 60 pixels wide), then 60/3 yeilds 20. Since each segment has a width of 20 pixels, a width of 60 by six gives the correct answer of 10.

+4
source

For our project, we needed the actual personnel of each segment, the separation of personnel was not enough. Here, the function I wrote calculates the exact frame for each segment. Keep in mind that it refers to segmented actual views of the control, so it can break in any iOS update.

 - (CGRect)segmentFrameForIndex:(NSInteger)index inSegmentedControl:(UISegmentedControl *)control { // WARNING: This function gets frame from UISegment objects, undocumented subviews of UISegmentedControl. // May break in iOS updates. NSMutableArray *segments = [NSMutableArray arrayWithCapacity:self.numberOfSegments]; for (UIView *view in control.subviews) { if ([NSStringFromClass([view class]) isEqualToString:@"UISegment"]) { [segments addObject:view]; } } NSArray *sorted = [segments sortedArrayUsingComparator:^NSComparisonResult(UIView *a, UIView *b) { if (a.frame.origin.x < b.frame.origin.x) { return NSOrderedAscending; } else if (a.frame.origin.x > b.frame.origin.x) { return NSOrderedDescending; } return NSOrderedSame; }]; return [[sorted objectAtIndex:index] frame]; } 
+10
source

This can be done much easier without matching class names, provided that you are not using a custom segmented control (version of Swift)

 extension NSSegmentedControl { func frameForSegment(segment: Int) -> NSRect { var left : CGFloat = 0 for i in 0..<segmentCount { let w = widthForSegment(i) if i == segment { let off = CGFloat(i) + 2 // Account for separators and border. return NSRect(x: left + off, y: bounds.minY, width: w, height: bounds.height) } left += w } return NSZeroRect } } 
0
source

If someone is looking for a solution for NSSegmentedControl , I slightly modified @ erik-aigner answer. For a UISegmentedControl it should work in a similar way.

This version improves geometry calculation for interval and code as a whole. Disclaimer: It was tested only for the segmented control located on the toolbar.

 import AppKit public extension NSSegmentedControl { /// The width of a single horizontal border. public static let horizontalBorderWidth: CGFloat = 3 /// The height of a single vertical border. public static let verticalBorderWidth: CGFloat = 2 /// The horizontal spacing between segments. public static let horizontalSegmentSpacing: CGFloat = 1 /// Returns the frame of the specified segment. /// /// - Parameter segment: The index of the segment whose frame should be computed. /// - Returns: The frame of the segment or `.zero` if an invalid segment index is passed in. public func frame(forSegment segment: Int) -> NSRect { let y = bounds.minY - NSSegmentedControl.verticalBorderWidth let height = bounds.height var left = NSSegmentedControl.horizontalBorderWidth for index in 0..<segmentCount { let width = self.width(forSegment: index) if index == segment { return NSRect(x: left, y: y, width: width, height: height) } left += NSSegmentedControl.horizontalSegmentSpacing left += width } return .zero } } 
0
source

Source: https://habr.com/ru/post/1402165/


All Articles