2012-03-12 8 views
5

Estoy usando la nueva API UIAppearance en iOS 5 para darle un estilo a UISegmentedControl con gráficos personalizados. Necesito poder configurar algunos segmentos para que se deshabiliten a veces durante la ejecución, pero los métodos UIAppearance no parecen permitirme establecer una imagen de divisor para el estado UIControlStateDisabled.UISegmentedControl no respeta las imágenes de divisor configuradas para UIControlStateDisabled

estoy llamando:

[[UISegmentedControl appearance] setDividerImage:disabledSelectedImage 
            forLeftSegmentState:UIControlStateDisabled 
            rightSegmentState:UIControlStateSelected 
            barMetrics:UIBarMetricsDefault]; 

donde disabledSelectedImage es una imagen de tamaño variable a partir de este recurso:

disabled-selected-image

Sin embargo, cuando me puse el segmento izquierdo estar deshabilitado ([UISegmentedControl setEnabled:forSegmentAtIndex:]), la resultado es este:

UISegmentedControl UI glitch

Puede ver claramente que el UISegmentedControl se ha predeterminado para usar la imagen del divisor UIControlStateNormal - UIControlStateNormal.

parece perfectamente feliz para mí Para configurar una imagen de fondo usando UIControlStateDisabled

[[UISegmentedControl appearance] setBackgroundImage:disabledImage 
            forState:UIControlStateDisabled 
            barMetrics:UIBarMetricsDefault]; 

(y respeta la imagen proveo mientras que en el estado desactivado) pero no un divisor de imagen. ¿Alguien ha encontrado esto o ha encontrado una solución?

+0

Parece un error. Creo que deberías presentarlo en bugreport.apple.com. – jfortmann

+0

@jfortmann Creo que tienes razón, he cambiado el flujo por ahora para eliminar segmentos en lugar de deshabilitarlos. Parece que hay bastantes errores en la API 'UIAppearance' para' UISegmentedControl' –

+0

¡Gracias por archivar! – jfortmann

Respuesta

3

He decidido que esto debe ser un error de iOS y he presentado un radar con Apple. Mi solución al problema por ahora es eliminar segmentos, en lugar de deshabilitarlos.

+0

Hice [lo mismo] (http://openradar.appspot.com/10999544) a principios de esta semana. Me alegra ver que no soy el único. –

+0

@CoryKilger Observé su informe también mientras construía este control segmentado, pero afortunadamente no me afectó porque no tuve que seleccionar primero el segundo segmento. Voy a volver a publicar el suyo a través del radar, así que espero obtener más atención. –

0

No he tenido la necesidad de utilizar los controles de apariencia de iOS 5 pero si todo lo demás falla, podría agregar la imagen de tamaño variable como elemento secundario del control segmentado para cubrir la fealdad. Es un truco, pero puede funcionar y será relativamente compatible con versiones anteriores. Solo asegúrese de configurar las máscaras de autosizing apropiadamente.

+0

Planeo usar los controles segmentados personalizados en toda la aplicación, posiblemente con diferentes números de segmentos/posiciones, etc. Desafortunadamente, no creo que funcione para mí. –

+0

¿Por qué no crear su propia subclase de UISegmentedControl que agrega automáticamente la imagen redimensionable? – TigerCoding

1

Un poco de una solución fea, pero me las arreglé para solucionarlo con lo siguiente hasta que Apple lo corrige por sí mismo.

primero que hay que subclase UISegmentedControl y añadir lo siguiente:

@implementation MJSegmentedControl 

- (void)layoutSubviews 
{ 
    [super layoutSubviews]; 
    NSInteger cachedIndex = self.selectedSegmentIndex; 
    self.selectedSegmentIndex = 0; 
    self.selectedSegmentIndex = cachedIndex; 
} 

@end 
0

que tenían el mismo problema y lo que realmente parece que hay un error. Sin embargo, he encontrado una solución (una solución alternativa).

He usado el archivo XIB con un controlador. En el archivo XIB, el control segmentado se acaba de colocar y todas las personalizaciones se realizaron en el método -viewDidLoad.

Luego creé una subclase UIView que representaba toda la vista en el XIB. Posibilitó mover todo el código de personalización de vistas al método -awakeFromNib de esta subclase UIView. Después de mover este código, las imágenes del divisor se configuraron correctamente.

0

Como se sugiere por Fernando en este hilo: Customizing UISegmentedControl in iOS 5

Usted puede tratar de enviar la configuración de UISegmentedControl en la cola principal a través de:

dispatch_async(dispatch_get_main_queue(),^{ 
    // disable part of the segmented control 
    [self.eventScopeSegmentedControl setEnabled:NO forSegmentAtIndex:2]; 
}); 

hice esto en viewDidLoad y ha funcionado muy bien para una mientras que cuando mi aplicación está realmente ocupada en el inicio, esto no siempre funciona. Supongo que hay una condición de carrera que aún puede revertir cualquier configuración que haya realizado cuando el proxy de aparición entre en funcionamiento.

Agregué otro hack feo para realizar esta llamada en viewWillAppear (después de la llamada a super: viewWillAppear) con un indicador (establecido desde viewWillLoad) para garantizar que solo se ejecute una vez.

0

En realidad, hay una forma bastante sencilla de hacerlo. El comportamiento actual es obviamente un error, por lo que esta no es una solución ideal, sino simplemente una solución que funciona muy bien. A saber, use una UIView adicional como una "señal visual desactivada".

Los pasos generales:

  1. Añadir un UIView como un hermano a la UISegmentedControl. Asegúrese de que el UIView está en frente de la UISegmentedControl
  2. Aplicar el color deseado y una transparencia a la UIView para que coincida con su piel aplicación
  3. Mueva el UIView que ser exactamente en la parte superior de la UISegmentedControl
  4. Forma del UIView tener la arriba tamaño exacto de la UISegmentedControl
  5. Aplicar una esquina redondeada a la UIView para reflejar la forma exacta de la UISegmentedControl

Cuando se supone que el UISegmentedControl debe ser desactivado, simplemente mostrar la UIView y desactivar la interacción del usuario en el UISegmentedC ontrol.

Cuando se supone que el UISegmentedControl está habilitado, simplemente oculte el UIView y habilite la interacción del usuario en el UISegmentedControl.

En ambos casos, no cambie la propiedad UISegmentedControl.enabled.

Tenga en cuenta que parece que hay muchos pasos, pero todo esto puede codificarse para agregar soporte para deshabilitar su UISegmentedControl personalizado se convierte en un trazador de líneas 1 después de agregar esto a un método de control segmentado de configuración.

Así es como mi costumbre segmentado de control se ve en la aplicación de esta solución:

habilita el control segmentado

enabled segmented control

control segmentado "desactivada"

disabled segmented control

Éstos son algunos fragmentos de código de interés:

Forma la UIView para que coincida con la UISegementedControl (carga configuración tiempo)

UISegmentedControl* segmentedControl = ... 
    //Segmented Control disabled visual cue view 
    UIView* view = ... 

    //Step #2  
    view.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.6]; 

    //Step #3 and #4 
    view.frame = segmentedControl.frame; 

    //Step #5 
    view.layer.cornerRadius = 5 
    view.clipsToBounds = YES; 

    //Ensure this is disabled by default 
    view.userInteractionEnabled = NO; 

Activar/UISegementedControl (cambio de estado de tiempo de ejecución) "Disable"

BOOL segmentedControlEnabled = ... 

if(segmentedControlEnabled) { 
    segmentedControl.userInteractionEnabled = YES; 
    view.hidden = YES;  
} else {  
    segmentedControl.userInteractionEnabled = NO; 
    view.hidden = NO; 
} 

Eso es todo.

-

Cuestiones relacionadas