2012-03-19 37 views
4

在我的应用程序中,我使用了UIPopoverController,并使用了presentPopoverFromRect API。我现在正在做的就是将其设置为我整个UISegmentedControl的框架。不过,我想要比这更精确。有什么方法可以获得UISegmentedControl中特定索引的框架吗?从某个UISegmentedControl索引获取帧?

谢谢!

回答

4

如果段相等,为什么不只是将控件的宽度除以所选段的编号(+1,因为编号从0开始)? 编辑:像这个

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

这是超过6(我假设一个3段实现),因为你必须得到该段的中心和3会把它上线。如果你在这里做一些简单的数学(假设整个控制是60px宽),然后60/3个样本20.因为每个片段是20px宽,所以60的宽度超过6得到正确的答案10.

+0

你能告诉我你的意思只是让我更好地了解一个例子吗? – 2012-03-19 04:07:26

+0

检查编辑。 – CodaFi 2012-03-19 04:27:55

+0

我看到如果我有一个2段UISegmentedControl,并且我试图获得第二个段的中间,我会做整个CGRectMake,而对于x它会是:segmentedControl.frame.size.width/4? – 2012-03-19 04:33:02

10

对于我们的项目,我们需要每个细分市场的实际帧,帧分割是不够的。这是我写的一个函数,用于计算每个细分的精确帧。请注意,它会访问细分的控件实际子视图,因此它可能会在任何iOS更新中破解。

- (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]; 
} 
+1

P E R F E C T!谢谢 – SpaceDog 2014-06-11 01:03:44

0

这是可以做到很容易没有匹配的类名,提供您使用没有自定义分段控制(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

如果有人正在寻找一个解决方案NSSegmentedControl,我已经稍微修改@ erik-aigner的回答。对于UISegmentedControl它应该类似地工作。

该版本改进了间距和代码的几何计算。免责声明:仅针对放置在工具栏中的分段控件进行了测试。

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 
    } 

}