Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get frame from certain UISegmentedControl index?

In my app, I use a UIPopoverController and I use the presentPopoverFromRect API. What I am doing now is just setting it to the frame of my whole UISegmentedControl. However I want to be more precise than this. Is there any way to get the frame of a specific index in the UISegmentedControl?

Thanks!

like image 440
SimplyKiwi Avatar asked Mar 19 '12 03:03

SimplyKiwi


2 Answers

For our project we needed the actual frames of each segment, frame division wasn't enough. Here's a function I wrote that calculates the exact frame for every segment. Be aware that it accesses the segmented control actual subviews, so it might 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];
}
like image 103
Accatyyc Avatar answered Oct 20 '22 02:10

Accatyyc


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

-(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)]
}

It's over 6 (I'm assuming a 3 segment implementation), because you have to get the center of the segment, and 3 would put it on the lines. And if you do some simple math here (let's assume the whole control is 60 px wide), then 60/3 yeilds 20. Because each segment is 20 px wide, the width of 60 over six yields the correct answer 10.

like image 33
CodaFi Avatar answered Oct 20 '22 03:10

CodaFi