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

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

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

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 можно сделать построитель интерфейса или в коде as показанный. Однако Шаг 3 можно сделать только в коде
  • значения цвета, устанавливаемые с помощью обозначение типа "123.0 / 255.0" просто способ сделать значения RGB выделиться вместо нормализованного значения float, требуемые 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]];
        }
    }
}

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

почему Эппл не позволит вам изменить цвет стандартной 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];

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

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


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

вот моя измененная версия CustomSegmentedControl uihacker (см. кредит в комментарии). Идея заключается в том, что я меняю способ найти подзадачу, в которой должен быть изменен 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)