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


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

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

21 67

21 ответ:

Я нашел простой способ добавить цвет для выбранного сегмента в 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];
    }
}

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

вот самый простой способ изменить выбранный сегмент в любой цвет 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];

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

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

Примечания:

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

для этого вам просто нужно найти выбранный сегмент, например, путем итерации по подвидам сегментированного элемента управления и тестирования 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]];
        }
    }
}

To убедитесь, что элемент управления отображается правильно каждый раз, когда вид открывается пользователем, мне также пришлось переопределить -(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 не будет работать, чтобы обойти это я использовал grand central dispatch, чтобы изменить выбранный цвет через долю секунды следующим образом:

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

по какой-то причине 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];

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

Seb Kade "Я здесь чтобы помочь"

редактировать: Это решение не работает на 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];
    }
}

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

кроме того, я добавил поддержку interface builder и переопределил 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.м

#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's 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

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

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

чтобы прояснить ответ, приведенный выше @jothikenpachi, мы обнаружили, что следующая категория UISegmentController хорошо работает в iOS6 и позволяет использовать произвольную цветовую схему включения/выключения на сегментах. Кроме того, он будет терпеть неудачу изящно, если частные методы isSelected/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.

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

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

segmentControl.backgroundColor = customColor;

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

mySegmentedControl.tintColor = [UIColor redColor]

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

// 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];
        }
    }
}

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

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

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

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

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

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

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

надеюсь, что это помогает.

спасибо,

Madhup

вы можете пометить каждый из сегментов, а затем установить 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];  

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

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

}

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

- (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]];
            }
        }
    }
}
Try this solution.    

enter image description here

enter image description here

        @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.
- (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];
        }
    }
}

мне интересно, почему никто не упомянул о 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

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

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