【问题标题】:Customizing the colors of a UISegmentedControl自定义 UISegmentedControl 的颜色
【发布时间】:2010-11-14 20:44:31
【问题描述】:

有人知道自定义基于字符串的 UISegmentedControl 外观的方法吗?我正在尝试根据项目的选定状态来设置单元格的背景颜色和文本颜色。

或者,您是否知道一种动态创建 UIImage 的方法,其中包含自定义字符串? (例如,创建具有白色背景、覆盖文本、添加到分段控件的 UUImage)。

我知道分段控件中只能有字符串或图像...

【问题讨论】:

    标签: ios objective-c uisegmentedcontrol


    【解决方案1】:

    从 iOS13 开始,您将无法再修改分段控制器的色调颜色。如果需要自定义颜色,需要使用selectedSegmentTintColor

    self.yourSegmentControl.selectedSegmentTintColor = UIColor(red: 240.0/255.0, green: 183.0/255.0, blue: 0.0/255.0, alpha: 1.0)
    

    【讨论】:

      【解决方案2】:

      Swift 5.0

       if #available(iOS 13.0, *) {
           // For selected segment
            control.selectedSegmentTintColor = UIColor.red
       }
      
       // For control's background 
       control.layer.backgroundColor = UIColor.black.cgColor
      

      【讨论】:

        【解决方案3】:

        故事板解决方案

        Xcode 11

        选择控件,现在可以使用多种颜色选项。如果您需要进一步改进 - 请查看用户定义的运行时属性。

        【讨论】:

          【解决方案4】:

          UISegmentedControl 有一个 tintColor 属性——这允许您更改控件的颜色,但不能更改一般的“样式”(圆形、斜面形状):

          segmentedControl.tintColor = [UIColor blueColor];
          

          至于动态创建 UIImage,您可以创建一个 CGContext,在该上下文中执行任何您需要的绘图(包括字符串),然后从上下文的 CGImage 中获取一个 UIImage:

          CGContextRef drawContext = CGBitmapContextCreate(<many parameters>);
          //do drawing here
          CGImageRef finalImage = CGBitmapContextCreateImage(drawContext);
          UIImage *cellImage = [UIImage finalImage];
          

          请注意,如果您使用 UIView.appearance().tintColor = .myColor(或 ObjC 中的等价物)之类的代码,则很可能不会发生该效果。

          【讨论】:

          • 仅供参考:如果您使用类似UIView.appearance().tintColor = .myColor 的东西,请小心——我无法手动覆盖UISegmentedControl 的tintColor(既不是故事板也不是代码)所以UISegmentedControl.tintColor 继承自UIView 的 tintColor。因此我不得不改变那条线。
          • @Muli 随时将该信息编辑到我的答案中;答案原样(距离它的十岁生日还有几天!)比appearance() 的存在早了几年。
          • 需要注意的是,从 iOS 13 开始, tintColor 不再是 UISegmentedControl 的受支持属性,即使它没有被正式标记为已弃用。有关详细信息,请参阅下面 Vinny 的答案,但您需要改为设置 selectedSegmentTintColor。
          【解决方案5】:

          我想完成类似的事情 - 将所选段的背景颜色设置为一种颜色,而其余段的“轮廓”是不同的颜色。

          大量借鉴Portland Runner's answer,其想法是继承 UISegmentedControl,并重写 2 个方法来设置初始状态的样式以及捕获更改事件以在用户选择不同的段时自动设置样式。

          - (void)layoutSubviews {
              [super layoutSubviews];
              [self updateSegmentColors];
          }
          -(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
              [super touchesEnded:touches withEvent:event];
              [self updateSegmentColors];
          }
          - (void)updateSegmentColors {
              NSArray* segments = [self.subviews sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
                  // UISegmentedControl segments use UISegment objects (private API). But we can safely cast them to UIView objects.
                  float v1 = ((UIView *)obj1).frame.origin.x;
                  float v2 = ((UIView *)obj2).frame.origin.x;
                  if (v1 < v2) return NSOrderedAscending;
                  else if (v1 > v2) return NSOrderedDescending;
                  else return NSOrderedSame;
              }];
              for (int i=0; i<segments.count; i++) {
                  if (i == self.selectedSegmentIndex) {
                      [segments[i] setTintColor:[UIColor redColor]];
                  } else {
                      [segments[i] setTintColor:[UIColor grayColor]];
                  }
              }
          }
          

          【讨论】:

            【解决方案6】:

            字体颜色 swift 3 和 swift 4 如果你想改变

            对于未选择的项目

             segcntrl.setTitleTextAttributes(titleTextAttributes, for: .normal)
            

            对于选定的项目

              segcntrl.setTitleTextAttributes(titleTextAttributes, for: .selected)
            
            
            
            //MARK:- Segment color change
                self.segc.setTitleTextAttributes([NSAttributedStringKey.foregroundColor: 
            UIColor.white], for: UIControlState.selected)
                self.segc.setTitleTextAttributes([NSAttributedStringKey.foregroundColor: 
            UIColor.white], for: UIControlState.normal)
            

            【讨论】:

              【解决方案7】:

              这是一个适用于 iOS9 的示例代码,但它是一个 hack,在以后的版本中可能无法使用:

              UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:@[@"Title1", @"Title2"]];
              for (id segment in [segmentedControl subviews])
              {
                  for (id view in [segment subviews])
                  {
                      NSString *desc = [view description];
                      if ([desc containsString:@"UISegmentLabel"])
                      {
                          [segment setTintColor:([desc containsString:@"Title1"] ? [UIColor blueColor] : [UIColor greenColor])];
                      }
                  }
              }
              

              【讨论】:

                【解决方案8】:

                我发现执行此类操作的最佳方法是为分段控件上的不同 UIControlStates 设置不同的属性。

                self.segmentedControl.tintColor = [UIColor cb_Grey1Color];
                self.segmentedControl.backgroundColor = [UIColor cb_Grey3Color];
                NSDictionary *selectedAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                                    [UIFont cbGothamBookFontWithSize:13.0], NSFontAttributeName,
                                                    [UIColor whiteColor], NSForegroundColorAttributeName,
                                                    [UIColor cb_Grey1Color], NSBackgroundColorAttributeName, nil];
                [self.segmentedControl setTitleTextAttributes:selectedAttributes forState:UIControlStateSelected];
                NSDictionary *unselectedAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                                      [UIFont cbGothamBookFontWithSize:13.0], NSFontAttributeName,
                                                      [UIColor cb_Grey2Color], NSForegroundColorAttributeName,
                                                      [UIColor cb_Grey3Color], NSBackgroundColorAttributeName, nil];
                [self.segmentedControl setTitleTextAttributes:unselectedAttributes forState:UIControlStateNormal];
                

                【讨论】:

                • BackgroundColorAttribute 只是改变了标题的背景
                【解决方案9】:

                我可以通过 XCode 6 中的 Interface Builder 做到这一点。附加的是 tint 属性:

                【讨论】:

                  【解决方案10】:

                  这里的大多数答案都没有回答如何根据选定状态设置按钮颜色的具体问题,这意味着未选定状态需要另一种颜色。我为此苦苦挣扎了很长一段时间,并想分享我的解决方案供其他人使用。

                  我的示例使用带有三个段的UISegmentedControl。所有三个未选择的颜色应该相同,以使其具有统一的外观。第一个和最后一个段的选定状态具有唯一的颜色。

                  问题是分段控件不能保证顺序相同,因此在您来回选择时颜色会混淆。 Dan 发布了一个使用标签的解决方案,但不幸的是,它不再保证适用于 iOS 6 及更高版本。

                  大部分代码取自this post。我稍微改变了它以具有独特的选定颜色。

                  使它起作用的是排序,但请注意以下两条用于设置所选颜色的重要行:

                  NSInteger selectedIdx = betterSegmentedControl.selectedSegmentIndex;
                  [[sortedViews objectAtIndex:selectedIdx] setTintColor:[self.segmentColors objectAtIndex:selectedIdx]];
                  

                  - (void) updateSegmentColors
                  {
                      UIColor *checkColor = [UIColor colorWithRed: 29/255.0 green:166/255.0 blue:47/255.0 alpha:1.0];
                      NSArray *segmentColors = [[NSArray alloc] initWithObjects:checkColor, [UIColor blueColor], [UIColor redColor], nil];
                  
                      UISegmentedControl *betterSegmentedControl = self.StatusControl;
                  
                      // Get number of segments
                      NSUInteger numSegments = [betterSegmentedControl.subviews count];
                  
                      // Reset segment's color (non selected color)
                      for( int i = 0; i < numSegments; i++ ) {
                          // reset color
                          [[betterSegmentedControl.subviews objectAtIndex:i] setTintColor:nil];
                          [[betterSegmentedControl.subviews objectAtIndex:i] setTintColor:[UIColor blueColor]];
                      }
                  
                      // Sort segments from left to right
                      NSArray *sortedViews = [betterSegmentedControl.subviews sortedArrayUsingFunction:compareViewsByOrigin context:NULL];
                  
                      // Change color of selected segment
                      NSInteger selectedIdx = betterSegmentedControl.selectedSegmentIndex;
                      [[sortedViews objectAtIndex:selectedIdx] setTintColor:[self.segmentColors objectAtIndex:selectedIdx]];
                  
                      // Remove all original segments from the control
                      for (id view in betterSegmentedControl.subviews) {
                          [view removeFromSuperview];
                      }
                  
                      // Append sorted and colored segments to the control
                      for (id view in sortedViews) {
                          [betterSegmentedControl addSubview:view];
                      }
                  }
                  
                  
                  NSInteger static compareViewsByOrigin(id sp1, id sp2, void *context)
                  {
                      // UISegmentedControl segments use UISegment objects (private API). But we can safely cast them to UIView objects.
                      float v1 = ((UIView *)sp1).frame.origin.x;
                      float v2 = ((UIView *)sp2).frame.origin.x;
                      if (v1 < v2)
                          return NSOrderedAscending;
                      else if (v1 > v2)
                          return NSOrderedDescending;
                      else
                          return NSOrderedSame;
                  }
                  

                  我将代码放在它自己的方法中,因为我将这些分段控件加载到表格视图中,并且需要在加载(存储中的现有状态)以及用户更改选择时运行它。现在我只需要在有变化时致电[Self updateSegmentColors];

                  【讨论】:

                    【解决方案11】:
                    segmentedControl.tintColor = [UIColor colorWithRed:0.61176f green:0.61176f  blue:0.61176f  alpha:1.0f];
                    
                    segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
                    

                    【讨论】:

                      【解决方案12】:

                      你所要做的就是:

                      // Get an array of the subviews of a UISegmentedControl, for example myUISegmentedControl:
                      
                      NSArray *arri = [myUISegmentedControl subviews];
                      
                      // Change the tintColor of each subview within the array:
                      
                      [[arri objectAtIndex:0] setTintColor:[UIColor redColor]];
                      
                      [[arri objectAtIndex:1] setTintColor:[UIColor greenColor]];
                      

                      【讨论】:

                      • 在 iOS 7 上完美运行...你太棒了!
                      • 好东西好解决方案
                      • 解决方案不一致,顺序可能会改变
                      猜你喜欢
                      • 2011-12-22
                      • 2011-11-27
                      • 2013-08-23
                      • 2010-11-19
                      • 1970-01-01
                      • 2010-12-31
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多