2009-07-28 20 views
18

Est-ce que quelqu'un connaît un moyen de personnaliser l'apparence de la chaîne UISegmentedControl? J'essaie de définir la couleur d'arrière-plan de la cellule et la couleur du texte différemment en fonction de l'état sélectionné de l'élément.Personnalisation des couleurs d'un UISegmentedControl

Vous connaissez également un moyen de créer des UIImages à la volée pour inclure des chaînes personnalisées? (par exemple créer une image avec un fond blanc, superposer du texte, ajouter au contrôle segmenté).

Je sais que vous ne pouvez avoir des chaînes ou des images dans le contrôle segmentée ...

Cheers!

Répondre

17

UISegmentedControl possède une propriété tintColor - ce qui vous permet de changer la couleur du contrôle est, mais pas le « style » (la forme arrondie, biseautés) générale:

segmentedControl.tintColor = [UIColor blueColor]; 

En ce qui concerne la création UIImages sur la mouche, vous pouvez créer un CGContext, faire le dessin que vous devez dans ce contexte (y compris les chaînes), puis obtenir un UIImage de CGImage du contexte:

CGContextRef drawContext = CGBitmapContextCreate(<many parameters>); 
//do drawing here 
CGImageRef finalImage = CGBitmapContextCreateImage(drawContext); 
UIImage *cellImage = [UIImage finalImage]; 
10
segmentedControl.tintColor = [UIColor colorWithRed:0.61176f green:0.61176f blue:0.61176f alpha:1.0f]; 

segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar; 
9

Tout ce que vous avez à faire est:

// 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]]; 
+0

ne fonctionne pas pour moi –

+1

travaillé parfaitement sur iOS 7 ... vous êtes incroyable! – CommaToast

+1

Bonne solution sympa – DogCoffee

7

La plupart des réponses ici ne répond pas à la question précise de la façon de définir une couleur de bouton en fonction de l'état sélectionné qui implique une autre couleur est souhaitée pour état non sélectionné. Je me suis battu avec cela pendant un certain temps et je voulais partager ma solution pour les autres à utiliser.

Mon exemple utilise un UISegmentedControl avec trois segments. La couleur non sélectionnée pour les trois doit être la même pour lui donner un aspect uniforme. L'état sélectionné pour le premier et le dernier segment possède des couleurs uniques.

enter image description here

Le problème est que le contrôle segmentée n'est pas garanti d'être dans le même ordre si les couleurs se mélangeront que vous sélectionnez dans les deux sens. Dan a posté une solution qui utilise des balises mais malheureusement, il n'est plus garanti de fonctionner pour iOS 6 et plus.

La plus grande partie de ce code provient de this post. Je l'ai légèrement changé pour avoir des couleurs sélectionnées uniques.

Ce qui rend le travail est le tri, mais prendre note de ces 2 lignes importantes pour le réglage de la couleur sélectionnée:

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

J'ai placé le code dans sa propre méthode parce que Je charge ces contrôles segmentés dans une vue de table et j'ai besoin de l'exécuter lors du chargement (états existants depuis le stockage) et lorsqu'un utilisateur change une sélection. Maintenant, je dois juste appeler [Self updateSegmentColors]; quand quelque chose change.

1

J'ai été capable de le faire via Interface Builder dans XCode 6.Ci-joint la propriété teinte:

enter image description here

6

La meilleure façon que j'ai trouvé de faire quelque chose comme cela est la mise en différents attributs pour différents UIControlStates sur le contrôle segmentée.

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]; 
+0

BackgroundColorAttribute change juste l'arrière-plan du titre –

2

Voici un exemple de code qui fonctionne avec iOS9, mais il est un hack, et peut ne pas fonctionner dans les versions ultérieures:

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])]; 
     } 
    } 
} 
0

que je voulais accomplir quelque chose de similaire - définir la couleur d'arrière-plan le segment sélectionné à une couleur tandis que le «contour» du reste des segments étaient d'une couleur différente. Empruntant lourdement à la réponse de Portland Runner, l'idée est de sous-classer UISegmentedControl et de surcharger 2 méthodes pour styliser l'état initial et capturer l'événement change pour le styliser automatiquement lorsque l'utilisateur sélectionne différents segments.

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

rapide Couleur de police 3 et rapide 4 si vous voulez changer

Pour article Unselected

segcntrl.setTitleTextAttributes(titleTextAttributes, for: .normal) 

Pour l'article sélectionné

segcntrl.setTitleTextAttributes(titleTextAttributes, for: .selected)