自定义 UISegmentedControl

38

如何制作自定义的UISegmentedControl

我有两张图片,一张应在片段处于活动状态时显示,另一张则在片段处于非活动状态时显示。我能否覆盖样式或其他内容,以便我拥有一个可以使用我自己的图像作为活动/非活动背景的UISegmentedControl

10个回答

33

除了拥有“开”和“关”两个状态之外,我还必须添加这个额外的代码:

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Set set segControl background to transparent
    CGRect rect = CGRectMake(0, 0, 1, 1);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
    CGContextFillRect(context, rect);
    UIImage *transparentImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    [self.segControl setBackgroundImage:transparentImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

    [self.segControl setDividerImage:transparentImage forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
}

编辑:由于此问题已经引起了一些关注,更好的解决方案是使用[UIImage new]代替创建透明图像,如下所示:

 [self.segControl setDividerImage:[UIImage new] forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
 [self.segControl setBackgroundImage:[UIImage new] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

这很棒,解决了最后一部分的问题(为我删除了黑色背景,我的分段图像有洞),但不幸的是,它只适用于ios5+。没有找到任何快速解决方案,所以我用几个按钮替换了分段控件。 - MANIAK_dobrii
这样会失去圆角,有什么方法可以保留它们吗? - MobileMon
这也将失去绘制在分段控件周围的边框。有什么方法可以保留它吗? - MobileMon

15
您可以使用iOS开发库中描述的方法:http://developer.apple.com/library/ios/ipad/#documentation/uikit/reference/UISegmentedControl_Class/Reference/UISegmentedControl.html。请向下滚动至“自定义外观”部分。有一些方法可用于设置多个按钮状态的背景图像、按钮分隔图像等。
这些方法仅适用于iOS5及以上版本。
@property tintColor  
 backgroundImageForState:barMetrics:
 setBackgroundImage:forState:barMetrics:
 contentPositionAdjustmentForSegmentType:barMetrics:
 setContentPositionAdjustment:forSegmentType:barMetrics:
 dividerImageForLeftSegmentState:rightSegmentState:barMetrics:
 setDividerImage:forLeftSegmentState:rightSegmentState:barMetrics:
 titleTextAttributesForState:
 setTitleTextAttributes:forState:

1
一个很好的资源,可以在这里找到如何使用它们的说明:http://smnh.me/customizing-appearance-of-uisegmentedcontrol/ - ospr

9
最简单的方法是创建一个类似于UISegmentedControl的控件。 UISegmentedControl只是排列一系列按钮,并为您管理它们的图像状态;它没有做任何特殊的事情。

6
我写了一些东西,可以像@rpetrich解释的那样工作,而不需要放在数组中。我认为这是最简单的解决方案。希望有人会发现这很有用。
.h
IBOutlet UIButton *index0;
IBOutlet UIButton *index1;
IBOutlet UIButton *index2;
IBOutlet UIImageView *segMentControl;

-(IBAction)segmentSwitch:(UIButton *) buttonIndexPressed;

.m

-(IBAction)segmentSwitch:(UIButton *) buttonIndexPressed
{
    if (buttonIpressed == index0)
    {
        [segmentControl setImage:[UIImage imageNamed:@"Seg1Sel.png"]];
        NSLog(@"index 0 pushed");

        index0.enabled = NO;
        index1.enabled = YES;
        index2.enabled = YES;        
    }
    else if (buttonIpressed == index1)
    {
         [segmentControl setImage:[UIImage imageNamed:@"Seg2Sel.png"]];
         NSLog(@"index 1 pushed");

         index0.enabled = YES;
         index1.enabled = NO;
         index2.enabled = YES;
    }
    else if (buttonIpressed == index2)
    {
        [segmentControl setImage:[UIImage imageNamed:@"Seg3Sel.png"]];
        NSLog(@"index 2 pushed");

        index0.enabled = YES;
        index1.enabled = YES;
        index2.enabled = NO;
    }
}

6

是的,对于段条的每个部分,您确实需要两个图像(开和关)。(4个段... 8个图像。)但它可以让您设置总共16个选择!(所有这些只消耗您GUI中的一行。)

我已经把所有东西都弄好了,除了...如何隐藏原始的段条图形?

不能将alpha设置为0。(它也会隐藏您的图像。)

不能将"tintClear"设置为"clear"。(不知道为什么会变成黑白。)

不能将其设置为"hidden"...根本无法工作。

不能将"background"设置为"clear"。(背景不是段条图形。)


2

它工作得非常好。

[segmentControl setImage:[UIImage imageNamed:@"Rolenew.png"] forSegmentAtIndex:0];

1

0

Jon的答案的Swift 3.0版本。

var transparentImage = UIGraphicsGetImageFromCurrentImageContext() as? UIImage
UIGraphicsEndImageContext()
segControl.setBackgroundImage(transparentImage, for: .normal, barMetrics: .default)
segControl.setDividerImage(transparentImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)

0

是的,我考虑过这个问题,但它会给我带来两个问题。
  1. 我看到我的图像下面有UIsegmentedcontroll。
  2. 如果我用这种方式,我必须为每个单独的段创建2个图像,因为一个段只能包含一个标题或一个图像。
- Robbert

0

Swift 4

这是我的解决方案。创建一个分段控制器并使用图像插入各个分段。确保将一个图像设置为默认选中的索引。 还要将backgroundColortintColor设为透明,这样分段控制器将只显示您的图像。

var newSegmentedControl: UISegmentedControl = {
        let segmentedControl = UISegmentedControl()

        segmentedControl.insertSegment(with: UIImage(named: "x_Selected.jpg"), at: 0, animated: true)
        segmentedControl.insertSegment(with: UIImage(named: "y_Normal.jpg"), at: 1, animated: true)

        segmentedControl.addTarget(self, action: #selector(segmentedControlChanged), for: .valueChanged)

        segmentedControl.selectedSegmentIndex = 0
        segmentedControl.backgroundColor = .clear
        segmentedControl.tintColor = .clear            

    }()

当分段控件的值改变时调用的函数。
@objc func segmentedControlChanged(sender: UISegmentedControl) {

    if sender.selectedSegmentIndex == 0 {
        sender.setImage(UIImage(named: "x_Selected.jpg"), forSegmentAt: sender.selectedSegmentIndex)
        sender.setImage(UIImage(named: "y_Normal.jpg"), forSegmentAt: 1)
    } else if sender.selectedSegmentIndex == 1 {
        sender.setImage(UIImage(named: "x_Normal.jpg"), forSegmentAt: 0)
        sender.setImage(UIImage(named: "y_Selected.jpg"), forSegmentAt: sender.selectedSegmentIndex)
    } 

}

希望您觉得这个有用 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接