UISegmentedControl выбран цвет сегмента

Есть ли способ настроить цвет выделенного сегмента в UISegmentedControl?

Я нашел свойство segmentedController.tintColor, которое позволяет настраивать цвет всего сегментарного элемента управления. Проблема заключается в том, что, когда я выбираю яркий цвет для свойства tintColor, выбранный сегмент становится почти неузнаваем (его цвет почти такой же, как и остальная часть сегментированного элемента управления, поэтому трудно отличить выбранные и невыбранные сегменты). Поэтому я не могу использовать хорошие яркие цвета для сегментированного управления. Решение было бы отдельным свойством для выбранного цвета сегмента, но я не могу его найти. Кто-нибудь решил это?

Ответ 1

Я нашел простой способ добавления цвета для выбранного сегмента в UISegmentcontrol

отправитель - UISegmentControl

for (int i=0; i<[sender.subviews count]; i++) 
{
    if ([[sender.subviews objectAtIndex:i]isSelected] ) 
    {               
    UIColor *tintcolor=[UIColor colorWithRed:127.0/255.0 green:161.0/255.0 blue:183.0/255.0 alpha:1.0];
    [[sender.subviews objectAtIndex:i] setTintColor:tintcolor];
    }
   else 
    {
        [[sender.subviews objectAtIndex:i] setTintColor:nil];
    }
}

Проверьте его работу для меня

Ответ 2

Вот самый простой способ изменить выделенный сегмент на любой цвет RGB. Не требуется подклассов или хаков.

segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;

UIColor *newTintColor = [UIColor colorWithRed: 251/255.0 green:175/255.0 blue:93/255.0 alpha:1.0];
    segmentedControl.tintColor = newTintColor;

UIColor *newSelectedTintColor = [UIColor colorWithRed: 0/255.0 green:175/255.0 blue:0/255.0 alpha:1.0];
[[[segmentedControl subviews] objectAtIndex:0] setTintColor:newSelectedTintColor];

В этом примере показаны важные шаги:

  • Устанавливает стиль управления для "StyleBar", который требуется для него работать
  • Устанавливает не выбранный цвет для весь контроль сначала до оранжевого.
  • Устанавливает цвет выбранного сегмент зеленый

Примечания:

  • Шаги 1 и 2 можно сделать в конструктор интерфейса или код в виде показано на рисунке. Однако шаг 3 может быть сделан только в коде
  • Значения цветов, заданные с помощью обозначение типа "123.0/255.0" просто способ сделать значения RGB выделяются вместо нормализованного значения поплавка, требуемые UIColor (просто игнорируйте его, если хотите)

Ответ 3

Для этого вам просто нужно найти выбранный сегмент, например, путем итерации по сегментированным подзонам управления и тестирования свойства isSelected, а затем просто вызовите метод setTintColor: в этом подвью.

Я сделал это, подключив действие к каждому сегментированному элементу управления в событии ValueChanged в Interface Builder, я подключил их к этому методу в файле контроллера вида, который по существу msprague отвечает:

- (IBAction)segmentedControlValueChanged:(UISegmentedControl*)sender
{
    for (int i=0; i<[sender.subviews count]; i++)
    {
        if ([[sender.subviews objectAtIndex:i] respondsToSelector:@selector(isSelected)] && [[sender.subviews objectAtIndex:i]isSelected])
        {
            [[sender.subviews objectAtIndex:i] setTintColor:[UIColor whiteColor]];
        }
        if ([[sender.subviews objectAtIndex:i] respondsToSelector:@selector(isSelected)] && ![[sender.subviews objectAtIndex:i] isSelected])
        {
            [[sender.subviews objectAtIndex:i] setTintColor:[UIColor blackColor]];
        }
    }
}

Чтобы гарантировать правильное отображение элемента управления при каждом открытии представления пользователем, мне также пришлось переопределить метод -(void)viewDidAppear:animated и вызвать метод следующим образом:

-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    //Ensure the segmented controls are properly highlighted
    [self segmentedControlValueChanged:segmentedControlOne];
    [self segmentedControlValueChanged:segmentedControlTwo];
}

Для некоторых бонусных очков, если вы хотите, чтобы сегментированный элемент управления использовал цвет белого оттенка при выборе, вы также захотите изменить цвет текста на черный, когда он будет выбран, вы можете сделать это следующим образом:

//Create a dictionary to hold the new text attributes
NSMutableDictionary * textAttributes = [[NSMutableDictionary alloc] init];
//Add an entry to set the text to black
[textAttributes setObject:[UIColor blackColor] forKey:UITextAttributeTextColor];
//Set the attributes on the desired control but only for the selected state
[segmentedControlOne setTitleTextAttributes:textAttributes forState:UIControlStateSelected];

С введением iOS 6 настройка цвета оттенка выбранного элемента в первый раз в методе viewDidAppear не будет работать, чтобы обойти это, я использовал большую центральную отправку, чтобы изменить выбранный цвет после доля секунды такая:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.05 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        [self segmentedControlValueChanged:segmentedControlOne];
    });

Ответ 4

По какой-то причине Apple не позволяет вам изменять цвет стандартных UISegmentedControls.

Тем не менее существует "законный" способ, который заключается в том, чтобы изменить сегментированный стиль управления на UISegmentedControlStyleBar. Это делает его немного отличающимся, что вам может не понравиться, но оно позволяет цвет.

    NSArray *itemArray = [NSArray arrayWithObjects: @"One", @"Two", @"Three", nil];
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:itemArray];

//Измените стиль и объявление в панели объявлений, затем отпустите сегментированный контроллер

segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
segmentedControl.tintColor = [UIColor colorWithRed:.9 green:.1 blue:.1 alpha:1]; 
[self.view addSubview:segmentedControl];
[segmentedControl release];

Надеюсь, это помогло,

Себ Каде "Я здесь, чтобы помочь"

Ответ 5

Изменить. Это решение не работает на iOS 6. См. ниже ответ Дэвид Томпсон.

Этот поток действительно старый, но ни один из простых ответов не работал правильно для меня.

Принятый ответ работает до тех пор, пока вы отмените цвет отложенных сегментированных элементов управления. Что-то вроде этого будет работать в вашей измененной функции:

for (int i=0; i<[control.subviews count]; i++) 
{
    if ([[control.subviews objectAtIndex:i]isSelected] ) 
    {               
        UIColor *tintcolor=[UIColor colorWithRed:127.0/255.0 green:161.0/255.0 blue:183.0/255.0 alpha:1.0];
        [[control.subviews objectAtIndex:i] setTintColor:tintcolor];
    } else {
        UIColor *tintcolor=[UIColor grayColor]; // default color
        [[control.subviews objectAtIndex:i] setTintColor:tintcolor];
    }
}

Ответ 6

Вот моя измененная версия uihacker CustomSegmentedControl (см. комментарий в комментарии). Идея заключается в том, что я изменяю способ поиска subview, который должен иметь изменение tintColor, с использованием метода selectedIndex to isSelected. Потому что я работал с пользовательским UISegmentedControl, который имеет 3 или более сегментов, которые упорядочивают порядок подсмотра (даже флаг uihacker hasSetSelectedIndexOnce не исправляет это!). Код все еще находится на раннем этапе разработки, поэтому используйте его на свой страх и риск. Любые комментарии приветствуются:)

Кроме того, я добавил поддержку конструктора интерфейсов и переопределил setSelectedSegmentIndex, чтобы он также обновлял цвет. Наслаждайтесь!

CustomSegmentedControl.h

//
//  CustomSegmentedControl.h
//
//  Created by Hlung on 11/22/54 BE.
//  Copyright (c) 2554 __MyCompanyName__. All rights reserved.
//
//  Credit: http://uihacker.blogspot.com/2010/05/iphone-uisegmentedcontrol-custom-colors.html

@interface CustomSegmentedControl : UISegmentedControl {
    UIColor *offColor,*onColor;
}
@property (nonatomic,retain) UIColor *offColor,*onColor;
-(id)initWithItems:(NSArray *)items offColor:(UIColor*)offcolor onColor:(UIColor*)oncolor;
@end

CustomSegmentedControl.m

#import "CustomSegmentedControl.h"

@interface CustomSegmentedControl (private)
-(void)setInitialMode;
-(void)toggleHighlightColors;
@end

@implementation CustomSegmentedControl

@synthesize offColor,onColor;

-(id)initWithItems:(NSArray *)items offColor:(UIColor*)offcolor onColor:(UIColor*)oncolor {
    if (self = [super initWithItems:items]) {
        // Initialization code
        self.offColor = offcolor;
        self.onColor = oncolor;
        [self setInitialMode];

        // default to 0, other values cause arbitrary highlighting bug
        [self setSelectedSegmentIndex:0];
    }
    return self;
}
- (void)awakeFromNib {
    // default colors
    self.offColor = [UIColor colorWithWhite:0.8 alpha:1];
    self.onColor = self.tintColor;
    [self setInitialMode];

    [self setSelectedSegmentIndex:0];
}

-(void)setInitialMode
{
    // set essential properties
    [self setBackgroundColor:[UIColor clearColor]];
    [self setSegmentedControlStyle:UISegmentedControlStyleBar];

    // loop through children and set initial tint
    for( int i = 0; i < [self.subviews count]; i++ )
    {
        [[self.subviews objectAtIndex:i] setTintColor:nil];
        [[self.subviews objectAtIndex:i] setTintColor:offColor];
    }

    // listen for updates, [self setSelectedSegmentIndex:0] triggers UIControlEventValueChanged in 5.0, 4.3 doesn't (facepalm), use  if( self.window ) to fix this
    [self addTarget:self action:@selector(toggleHighlightColors) forControlEvents:UIControlEventValueChanged];
}

// ---------------
// hlung version
// ---------------
-(void)toggleHighlightColors
{
    // the subviews array order randomly changes all the time, change to check for "isSelected" instead
    for (id v in self.subviews) {
        if ([v isSelected]) [v setTintColor:onColor];
        else [v setTintColor:offColor];
    }
}
// override: update color when set selection
- (void)setSelectedSegmentIndex:(NSInteger)selectedSegmentIndex {
    [super setSelectedSegmentIndex:selectedSegmentIndex];
    [self toggleHighlightColors];
}
// ---------------
@end

Ответ 7

Не уверен, что это будет одобрено магазином приложений, но я написал подкласс для UISegmentedControl, который позволяет вам установить пользовательский выбранный и невыбранный цвет. Проверьте заметки для получения дополнительной информации:

http://uihacker.blogspot.com/2010/05/iphone-uisegmentedcontrol-custom-colors.html

Ответ 8

Чтобы пояснить ответ, приведенный выше, @jothikenpachi, мы обнаружили, что следующая категория UISegmentController хорошо работала в iOS6 и допускает произвольную цветовую схему включения/выключения на сегментах. Плюс это будет неудачно изящно, если частные методы areSelected/setTintColor: будут изменены в будущих выпусках ОС. Предостережения вокруг частных вызовов API и т.д.

@implementation UISegmentedControl(CustomTintExtension) {
-(void) updateCustomTintColorOn:(UIColor*)onColor Off:(UIColor*)offColor {
// Convenience function to rest the tint colors after selection, called upon change of selected index

SEL tint = @selector(setTintColor:);

for (UIView *view in [self subviews]) {
    // Loop through the views...
    if (view && ([view respondsToSelector:tint])) {
        [view performSelector:tint withObject:nil];
    }
    if (view && ([view respondsToSelector:tint])) {
        [view performSelector:tint withObject:offColor];
    }
}

// Checking if segment subview is selected...
SEL isSelected = @selector(isSelected);
for (UIView *view in [self subviews]) {
    if ([view respondsToSelector:isSelected] && [view performSelector:isSelected withObject:nil])
    {
        [view performSelector:tint withObject:onColor];
        break;
    }
}

}

Примечание. Этот метод категории будет вызываться из метода UISegmentController - (IBAction) segmentAction: (id)sender.

Также обратите внимание, что с iOS6 кажется, что вам, возможно, придется сначала вызвать этот метод в управляющем UIViewController - (void)viewDidAppear:(BOOL)animated, который может привести к анимационной вспышке. Чтобы свести к минимуму это, попробуйте установить "offColor" как TintColor UISegmentController в IB.

Ответ 9

Я просто столкнулся с этой проблемой на iOS 7, которая работает иначе, чем iOS6.

В iOS 7 цвет метки для выбранного сегмента имеет тот же цвет, что и фон UISegementControl. Единственный способ изменить его на iOS 7 - установить цвет фона UISegmentControl.

segmentControl.backgroundColor = customColor;

Ответ 10

Используйте это:

[[UISegmentedControl appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor colorWithRed:255.0/255 green:37.0/255 blue:99.0/255 alpha:1.0]} forState:UIControlStateSelected];

Ответ 11

Я использовал это, и он изменил все цвета за один шаг.

mySegmentedControl.tintColor = [UIColor redColor]

Ответ 12

Я обнаружил, что я могу использовать тег в subviews с тем же индексом, что и сегменты, так что в любом порядке сегменты будут правильно окрашены.

// In viewWillAppear set up the segmented control 

// then for 3 segments:  
self.navigationItem.titleView = segmentedControl;
//Order of subviews can change randomly!, so Tag them with same index as segment
[[[segmentedControl subviews]objectAtIndex:0]setTag:0]; 
[[[segmentedControl subviews]objectAtIndex:1]setTag:1];
[[[segmentedControl subviews]objectAtIndex:2]setTag:2];


// color follows the selected segment
- (IBAction)mySelector:(id)sender {
selector = [sender selectedSegmentIndex]
  for (id seg in [segmentedControl subviews]) {
    for (id label in [seg subviews]) {
        if ([seg tag] == selector){
            [seg setTintColor:selectedColor];
        } else {
            [seg setTintColor:nonSelectedColor];
        }
    }
  }
}

// in viewDidAppear for returning to the view
[segmentedControl setSelectedSegmentIndex:selector];
for (id seg in [segmentedControl subviews]) {
    for (id label in [seg subviews]) {
        if ([seg tag] == selector){
            [seg setTintColor:selectedColor];
        } else {
            [seg setTintColor:nonSelectedColor];
        }
    }
}

Ответ 13

Два лучших решения не работали для меня при переключении между сегментами.

Мое решение состояло в том, чтобы обрабатывать событие изменения сегмента в моем контроллере представления, а затем вызывать этот метод каждый раз, когда сегмент изменяется:

+ (void)setSegmentedControl:(UISegmentedControl *)segmentedControl 
              selectedColor:(UIColor *)selectedColor 
            deselectedColor:(UIColor *)deselectedColor
{
    for (int i = 0; i < segmentedControl.subviews.count; i++) 
    {
        id subView = [segmentedControl.subviews objectAtIndex:i];

        if ([subView isSelected])
            [subView setTintColor:selectedColor];
        else
            [subView setTintColor:deselectedColor];
    }    
}

Ответ 14

Мне интересно, почему никто не упомянул про UIAppearanceProxy

Apple Doc ::

https://developer.apple.com/documentation/uikit/uisegmentedcontrol#1653545

Пример кода:

    private class func applyUISegmentControlAppearance(){
    let apperance = UISegmentedControl.appearance()

    // Set Navigation bar Title colour
    let unselAttrib = [NSForegroundColorAttributeName:UIColor.yellow,
                                        NSFontAttributeName: UIFont.systemFont(ofSize: 15)]

    let selAttrib = [NSForegroundColorAttributeName:UIColor.red,
                     NSFontAttributeName: UIFont.boldSystemFont(ofSize: 15)]


    apperance.setTitleTextAttributes(unselAttrib, for: .normal)
    apperance.setTitleTextAttributes(selAttrib, for: .selected)
}

Позвонить: Вы можете вызвать этот метод в AppDelegate из

application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool

Ответ 15

Для того, чтобы делать что-то вроде этого, вам может потребоваться доступ к недокументированным функциям и хакам, что, безусловно, сделает ярость яблоком, и это может привести к отказу от вашего приложения.

Теперь решение заключается в другом трюке, что вместо этого вы используете две кнопки и меняете изображения, когда их нажимают. Держите кнопки ближе и изображения полусегментированного элемента управления, чтобы создать иллюзию сегментированного управления, и это все, что я могу вам предложить.

Надеюсь, что это поможет.

Спасибо,

Madhup

Ответ 16

Вы можете пометить каждый из сегментов, а затем установить TintColor forTag:

#define kTagOffState 0
#define kTagOnState  2

#define UIColorFromRGB(rgbValue) [UIColor \
        colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \
        green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \
        blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]

//usage     UIColor color = UIColorFromRGB(0xF7F7F7);

 UIColor onColor = UIColorFromRGB(0xF7F7F7);
 UIColor offColor = UIColorFromRGB(0x878787);

        [multiStateControl setTag:kTagOffState forSegmentAtIndex:0];
        [multiStateControl setTag:kTagOnState forSegmentAtIndex:1];
        [multiStateControl setTintColor:onColor forTag:kTagOnState];
        [multiStateControl setTintColor:offColor forTag:kTagOffState];  

Ответ 17

Я нашел ответы выше очень полезными. Я использую сегментированный элемент управления, чтобы установить точность ручки. Я взял гибрид ответов выше и придумал следующее:

-(void) viewDidLoad {

NSArray *segments = [NSArray arrayWithObjects:@"Course", @"Fine",nil];

[knob setPrecision:0.1]; // initial precision
// Set starting values

UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:segments];

segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
segmentedControl.frame = CGRectMake(120, 680, 228, 30);
[segmentedControl addTarget:self action:@selector(precisionSelect:) forControlEvents:UIControlEventValueChanged];
segmentedControl.momentary = YES;

[self.view addSubview:segmentedControl];
}   

- (void)precisionSelect:(UISegmentedControl*)sender
{   
    UIColor *tintcolor = [UIColor darkGrayColor];   
    if (sender.selectedSegmentIndex == 0) {
        [[sender.subviews objectAtIndex:0] setTintColor:nil];
        [[sender.subviews objectAtIndex:1] setTintColor:tintcolor];
    [knob setPrecision:0.1]; // Coarse
    } else {
        [[sender.subviews objectAtIndex:0] setTintColor:tintcolor];
        [[sender.subviews objectAtIndex:1] setTintColor:nil];
    [knob setPrecision:0.05]; // Fine
    }

}

Надеюсь, это поможет другим. Ключом для меня был reset невыбранный индекс, используя: setTintColor:nil];

Ответ 18

- (IBAction)segmentControlValueChanged:(UISegmentedControl *)sender
{
    if ([[sender.subviews firstObject] respondsToSelector:@selector(setTintColor:)]) {
        for (id segment in sender.subviews) {
            if ([segment respondsToSelector:@selector(isSelected)] && [segment isSelected]) {
                [segment setTintColor:[UIColor redColor]];
            } else {
                [segment setTintColor:[UIColor grayColor]];
            }
        }
    }
}

Ответ 19

Try this solution.    

введите описание изображения здесь

введите описание изображения здесь

        @IBAction func dashBoardSegmentValueChanged(sender: AnyObject) {
            switch dashBoardSegment.selectedSegmentIndex
            {
            case 0:     
                sender.subviews.last?.backgroundColor = UIColor.whiteColor()
                sender.subviews.first?.backgroundColor =  UIColor.clearColor()

                break;
            case 1:            
                sender.subviews.first?.backgroundColor =  UIColor.whiteColor()
                sender.subviews.last?.backgroundColor = UIColor.clearColor()
                break;
            default:
                break;
            }
        }

Note: Make sure you select one segment subview as initial selected for easiness. It works if you have two segment subviews.

Ответ 20

- (IBAction)segmentedControlValueChanged:(UISegmentedControl *)sender {
    for (int i = 0; i < sender.subviews.count; i++) {
        UIControl *component = [sender.subviews objectAtIndex:i];
        if ([component respondsToSelector:@selector(isSelected)]) {
            UIColor *selectedColor = [UIColor greenColor];
            UIColor *normalColor   = [UIColor blackColor];
            UIColor *tint = component.isSelected ? selectedColor : normalColor;
            [component setTintColor:tint];
        }
    }
}

Ответ 21

[segmentedControl setSelectedSegmentTintColor:[UIColor darkGrayColor]];

//For iOS 13

Ответ 22

Этот код Swift 4 работает для меня

segmentedControl.setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor.red], for: .selected)