【问题标题】:UISegmentedControl setImage: Bug in iOS7UISegmentedControl setImage:iOS7 中的错误
【发布时间】:2013-09-14 20:33:30
【问题描述】:

我的应用中有一个 UISegmentedControl。从 iOS7 GM 开始,我使用的图像在 iOS7 设备上运行时不会显示。其他人有这个问题吗?

这是在 iOS6.1 及更早版本中的样子 .

这是它在 iOS7 中的样子 .

代码如下:

self.theSegmentedControl.frame = CGRectMake(self.theSegmentedControl.frame.origin.x, self.theSegmentedControl.frame.origin.y, 320, 35);
[self.theSegmentedControl setBackgroundImage:[UIImage imageNamed:@"img_toggleInactive"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[self.theSegmentedControl setImage:[UIImage imageNamed:@"btn_onceActive"] forSegmentAtIndex:0];
[self.theSegmentedControl setImage:[UIImage imageNamed:@"btn_recurringInactive"] forSegmentAtIndex:1];
[self.theSegmentedControl setImage:[UIImage imageNamed:@"btn_scheduledInactive"] forSegmentAtIndex:2];
[self.theSegmentedControl setDividerImage:[UIImage imageNamed:@"separator"] forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

有没有人找到解决方法?

【问题讨论】:

  • 这不是但是,这是一个功能! Apple 做出了一个非常奇怪的选择,将他的分段控件中的图像完全着色。在我的应用中,我使用 seg 来选择颜色,现在我的颜色都是蓝色的!

标签: objective-c cocoa-touch uisegmentedcontrol ios7


【解决方案1】:

哇哦!这是解决方法:

//Add clear color to mask any bits of a selection state that the object might show around the images
self.theSegmentedControl.tintColor = [UIColor clearColor];

UIImage *onceActive;
UIImage *recurringActive;
UIImage *scheduledActive;
UIImage *separator;

//Setting imageWithRenderingMode: to imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal for iOS7 is key
if ([UIImage instancesRespondToSelector:@selector(imageWithRenderingMode:)]) {
    onceActive = [[UIImage imageNamed:@"btn_onceActive"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    recurringActive = [[UIImage imageNamed:@"btn_recurringInactive"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    scheduledActive = [[UIImage imageNamed:@"btn_scheduledInactive"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    separator = [[UIImage imageNamed:@"separator"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

}
else {
    onceActive = [UIImage imageNamed:@"btn_onceActive"];
    recurringActive = [UIImage imageNamed:@"btn_recurringInactive"];
    scheduledActive = [UIImage imageNamed:@"btn_scheduledInactive"];
    separator = [UIImage imageNamed:@"separator"];
}


[self.theSegmentedControl setImage:onceActive forSegmentAtIndex:0];
[self.theSegmentedControl setImage:recurringActive forSegmentAtIndex:1];
[self.theSegmentedControl setImage:scheduledActive forSegmentAtIndex:2];
[self.theSegmentedControl setDividerImage:separator forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

【讨论】:

  • 这不是 WWDC 视频中明确指出的“解决方法”,在这种情况下需要做的事情
  • 没有新方法的代码在 iOS6.1 及更低版本中工作并在 7 中停止。文档或控制台中没有指示做任何不同的事情。观看所有 WWDC 视频的责任并不在于我。我会继续说这是一个错误,谢谢。
  • 您是否使用新的 SDK 重新编译了您的代码?文档清楚地 声明: Segment Icons 您可以使用图像而不是标题文本作为分段。请注意,除非您将其渲染模式显式设置为 UIImageRenderingModeAlwaysOriginal,否则分段图像将自动呈现为分段控件中的模板图像。有关更多信息,请参阅模板图像(我没有链接到它,因为链接仍然是预发布的)
  • 您说得对,过渡指南中提到了该行为,谢谢。
  • 我试过这个,但我设置的图像没有缩放来填充片段。见stackoverflow.com/questions/18850081/…
【解决方案2】:

Xcode 6/iOS 8 更新

现在您可以在界面生成器中进行操作

只需在资产目录中添加图像文件并将其“渲染为”原始图像而不是默认设置

Xcode 5

新的 UISegmented 控件使用 tint color 使用模板模式为图像着色。 您需要将这些图像渲染为原始图像,而不是模板。

按照 cmets 的建议,这样做:

UIImage* onceActive = [UIImage imageNamed:@"btn_onceActive"];
if (IOS_7_MACRO)
    onceActive = [onceActive imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
[self.theSegmentedControl setImage:onceActive forSegmentAtIndex:0];

【讨论】:

  • 如何告诉它使用 XIB/Interface Builder 中的 AlwaysOriginal 渲染模式?
  • 我没有在 IB 中看到这个选项,至少 UISegmentedControl :(
  • 从 Xcode 6 开始,您可以在资产目录属性中为每个资产设置渲染模式:D
  • 好像 iOS 7 忽略了这个设置。我使用的是 Xcode 6.1,该设置在 iOS 8 上运行时有效,但在 iOS 7 上无效。
  • @mahboudz 谢谢,我已经更新了答案。没有在 iOS 7 上测试自己,现在太懒了:D
【解决方案3】:

使用此代码在带有 xCode 5.0 的 iOS 7 中的段控制上设置图像

if ([UIImage instancesRespondToSelector:@selector(imageWithRenderingMode:)]) {

    [segmentControl setImage:[[UIImage imageNamed:@"image.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] forSegmentAtIndex:0];

}
else {
    [segmentControl setImage:[UIImage imageNamed:@"image.png"] forSegmentAtIndex:0];
}

【讨论】:

    【解决方案4】:

    创建一个类别可能很有用:

    @interface UISegmentedControl (UISegmentedControlAdditions)
        -(void)setImageRenderingMode:(UIImageRenderingMode)renderingMode;
    @end    
    
    @implementation UISegmentedControl (UISegmentedControlAdditions)
        -(void)setImageRenderingMode:(UIImageRenderingMode)renderingMode {
            for (int index=0; index < [self numberOfSegments]; index++) {
                UIImage * image = [self imageForSegmentAtIndex:index];
                [self setImage:[image imageWithRenderingMode:renderingMode] forSegmentAtIndex:index];
            }
        }
    

    ...然后打电话

    if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
        [colorSegmentedControl setImageRenderingMode:UIImageRenderingModeAlwaysOriginal];
    

    【讨论】:

    • imageWithRenderingMode: 已存在于UIImage 中。那为什么要创建类别呢?仅适用于 iOS 7.0 及更高版本。
    • 是的,imageWithRenderingMode: 也是一个UIImage 方法:这个例子正在使用它。为什么要创建一个类别?因为它比手动配置控件更简洁和有用。当然,创建自己的 UISegmentedControl 类会更好。
    猜你喜欢
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 2015-10-14
    相关资源
    最近更新 更多