iphone - UISegmentedControl selecciona el color del segmento
colors (21)
¿Hay alguna manera de personalizar el color del segmento seleccionado en UISegmentedControl
?
He encontrado la propiedad segmentedController.tintColor
, que me permite personalizar el color de todo el control segmentado. El problema es que cuando selecciono el color brillante para la propiedad tintColor
, el segmento seleccionado se vuelve casi irreconocible (su color es casi el mismo que el resto del control segmentado, por lo que es difícil distinguir segmentos seleccionados y no seleccionados). Entonces no puedo usar buenos colores brillantes para el control segmentado. La solución sería una propiedad separada para el color del segmento seleccionado, pero no puedo encontrarlo. ¿Alguien resolvió esto?
Acabo de toparme con este problema en iOS 7, que funciona de manera diferente a iOS6.
En iOS 7, el color de la etiqueta para el segmento seleccionado es del mismo color que el fondo UISegementControl. La única forma de cambiarlo en iOS 7 es establecer el color de fondo de UISegmentControl.
segmentControl.backgroundColor = customColor;
Aquí está mi versión modificada del CustomSegmentedControl de uihacker (ver crédito en el comentario). La idea es que cambie la forma de encontrar la subvista que debería haber cambiado el tintColor, desde el método selectedIndex a isSelected. Porque estaba trabajando con un UISegmentedControl personalizado que tiene 3 o más segmentos en los que el orden de la subvista cambia aleatoriamente (¡incluso el indicador "hasSetSelectedIndexOnce" de uihacker no soluciona esto!). El código todavía está en la etapa de desarrollo inicial, así que úsala bajo tu propio riesgo. Cualquier comentario es bienvenido :)
Además, agregué compatibilidad con el constructor de interfaz y anulé setSelectedSegmentIndex para que también actualizara el color. ¡Disfrutar!
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''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
Descubrí que podía usar etiquetas en las subvistas con el mismo índice que los segmentos, de modo que en cualquier orden los segmentos se colorearan correctamente.
// 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];
}
}
}
Encontré las respuestas de arriba muy útiles. Estoy usando el control segmentado para establecer la precisión de un mando. Tomé un híbrido de las respuestas anteriores y se me ocurrió esto:
-(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
}
}
Espero que esto ayude a los demás ... Una clave para mí fue poder restablecer el índice no seleccionado usando: setTintColor:nil];
Encontré una forma simple de agregar color para el segmento seleccionado en UISegmentcontrol
el remitente es 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];
}
}
Compruebe que funciona para mí
Esta es la forma más simple de cambiar el segmento seleccionado a cualquier color RGB. No se requieren subclases o hacks.
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];
Este ejemplo muestra los pasos importantes:
- Establece el estilo de control en "Barra de estilo", que es necesario para que funcione
- Establece el color no seleccionado para todo el control primero en naranja
- Establece el color del segmento seleccionado en verde
Notas:
- Los pasos 1 y 2 se pueden realizar en el constructor de interfaz o en el código como se muestra. Sin embargo, el paso 3 solo se puede hacer en código
- Los valores de color configurados con notación como esta "123.0 / 255.0" es solo una manera de resaltar los valores RGB en lugar de los valores de flotación normalizados requeridos por UIColor (simplemente ignórelo si lo desea)
Este código de Swift 4 funciona para mí
segmentedControl.setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor.red], for: .selected)
Las dos mejores soluciones no funcionaron para mí al cambiar de un segmento a otro.
Mi solución fue manejar el evento de cambio de segmento en mi controlador de vista y luego llamar a este método cada vez que se cambia el segmento:
+ (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];
}
}
Lo usé y cambió todos los colores en un solo paso.
mySegmentedControl.tintColor = [UIColor redColor]
Me pregunto por qué nadie ha mencionado sobre UIAppearanceProxy
Apple Doc ::
https://developer.apple.com/documentation/uikit/uisegmentedcontrol#1653545
Código de muestra:
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)
}
Llamar desde: Puedes llamar a este método en AppDelegate
desde
application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool
No estoy seguro de si la tienda de aplicaciones lo aprobará, pero escribí una subclase para UISegmentedControl que le permite establecer un color personalizado seleccionado y no seleccionado. Verifique las notas para obtener más información:
http://uihacker.blogspot.com/2010/05/iphone-uisegmentedcontrol-custom-colors.html
Para aclarar la respuesta proporcionada anteriormente por @jothikenpachi, encontramos que la siguiente categoría de UISegmentController funcionó bien en iOS6 y permite un esquema de colores on / off arbitrario en los segmentos. Además, fallará correctamente si los métodos privados isSelected / setTintColor: se cambian en futuras versiones del sistema operativo. Advertencias sobre llamadas API privadas, etc.
@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;
}
}
}
Tenga en cuenta que este método de categoría se invocará desde el método del remitente UISegmentController - (IBAction) segmentAction: (id)sender
.
También tenga en cuenta que con iOS6 parece que necesitará llamar a este método inicialmente en el controlador UIViewController''s - (void)viewDidAppear:(BOOL)animated
que puede dar como resultado un flash de animación. Para minimizar esto, intente configurar "offColor" como tintColor de UISegmentController en IB.
Para hacer su tipo de cosas, es posible que tenga que acceder a las funciones y pirateos no documentados, lo que ciertamente hará que Apple se ponga furioso, y eso puede llevar al rechazo de su aplicación.
Ahora, la solución radica en otro truco que utiliza dos botones en su lugar y sus imágenes se intercambian cuando se hace clic. Mantenga los botones más cerca y las imágenes de control medio segmentado para dar la ilusión de control segmentado y eso es todo lo que puedo sugerirle.
Espero que esto ayude.
Gracias,
Madhup
Para hacerlo, simplemente tiene que buscar el segmento seleccionado, por ejemplo, iterando sobre las subvistas del control segmentado y probando la propiedad isSelected
, luego simplemente llame al método setTintColor:
en esa subvista.
Lo hice conectando una acción a cada control segmentado en el evento ValueChanged en Interface Builder, los conecté a este este método en el archivo de controlador de vista que es esencialmente la respuesta de 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]];
}
}
}
Para garantizar que el control se muestra correctamente cada vez que el usuario abre la vista, también tuve que anular el método -(void)viewDidAppear:animated
y llamar al método de la siguiente manera:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
//Ensure the segmented controls are properly highlighted
[self segmentedControlValueChanged:segmentedControlOne];
[self segmentedControlValueChanged:segmentedControlTwo];
}
Para algunos puntos de bonificación si desea establecer el control segmentado para usar un color de tinte blanco en la selección, entonces también querrá cambiar el color del texto a negro cuando se seleccione, puede hacerlo de esta manera:
//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];
Con la introducción de iOS 6 estableciendo el color del tinte del elemento seleccionado por primera vez en el método viewDidAppear no funcionará, para evitar esto utilicé el despacho de grand central para cambiar el color seleccionado después de una fracción de segundo así:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.05 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self segmentedControlValueChanged:segmentedControlOne];
});
Por algún motivo, Apple no te permite cambiar el color de UISegmentedControls estándar.
Sin embargo, existe una manera "legal" de cambiar el estilo de control segmentado a UISegmentedControlStyleBar. Esto hace que se vea ligeramente diferente, lo cual puede no gustarle pero permite el color.
NSArray *itemArray = [NSArray arrayWithObjects: @"One", @"Two", @"Three", nil];
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:itemArray];
// Cambiar el estilo de barra y el anuncio para ver y luego liberar el controlador segmentado
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
segmentedControl.tintColor = [UIColor colorWithRed:.9 green:.1 blue:.1 alpha:1];
[self.view addSubview:segmentedControl];
[segmentedControl release];
Espero que esto haya ayudado,
Seb Kade "Estoy aquí para ayudar"
Puede etiquetar cada uno de los segmentos, luego establecer el 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];
Utilizar esta:
[[UISegmentedControl appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor colorWithRed:255.0/255 green:37.0/255 blue:99.0/255 alpha:1.0]} forState:UIControlStateSelected];
Editar : Esta solución no funciona en iOS 6. Consulte la respuesta de David Thompson a continuación.
Este hilo es muy viejo, pero ninguna de las respuestas simples funcionó correctamente para mí.
La respuesta aceptada funciona siempre que revierte el color de los controles segmentados no seleccionados. Algo así funcionará en su función de cambio de valor:
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];
}
}
- (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]];
}
}
}
}
- (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];
}
}
}
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.