2010-05-18 12 views
24

¿Hay alguna manera de establecer un estado personalizado, no uno de los valores existentes UIControlState, para un UIControl?¿Puedo usar valores personalizados de UIControlState para mi propio control?

En el UIControlSate enumeración, hay 16 bits que se pueden utilizar para los estados de control personalizados:

UIControlStateApplication = 0x00FF0000,    // additional flags available for application use 

El problema es que state propiedad UIControl 's es de sólo lectura .

Quiero establecer diferentes imágenes de fondo en mi UIButton para estados personalizados.

Respuesta

34

Puede hacer uso de los estados personalizados en una subclase de UIControl.

  • Cree una variable llamada customState en la que gestionará sus estados personalizados.
  • Si necesita establecer un estado, realice las operaciones de su marcador con esta variable y llame al [self stateWasUpdated].
  • sustituye a la propiedad state para volver [super state] bit a bit es OR en contra de su anulación customState
  • los enabled, selected y highlighted emisores de manera que ellos llaman [self stateWasUpdated]. Esto le permitirá responder a cualquier cambio en el estado, no sólo cambia a customState
  • Implementar stateWasUpdated con la lógica para responder a los cambios en el estado de

en la cabecera:

#define kUIControlStateCustomState (1 << 16) 

@interface MyControl : UIControl { 
    UIControlState customState; 
} 

En la puesta en práctica :

@implementation MyControl 

-(void)setCustomState { 
    customState |= kUIControlStateCustomState; 
    [self stateWasUpdated]; 
} 

-(void)unsetCustomState { 
    customState &= ~kUIControlStateCustomState; 
    [self stateWasUpdated]; 
} 

- (UIControlState)state { 
    return [super state] | customState; 
} 

- (void)setSelected:(BOOL)newSelected { 
    [super setSelected:newSelected]; 
    [self stateWasUpdated]; 
} 

- (void)setHighlighted:(BOOL)newHighlighted { 
    [super setHighlighted:newHighlighted]; 
    [self stateWasUpdated]; 
} 

- (void)setEnabled:(BOOL)newEnabled { 
    [super setEnabled:newEnabled]; 
    [self stateWasUpdated]; 
} 

- (void)stateWasUpdated { 
    // Add your custom code here to respond to the change in state 
} 

@end 
+4

La enumeración UIControlState especifica que los estados de control de aplicaciones utilizan la máscara 0x00FF0000. Eso significa 1 << 16 a 1 << 23. Utiliza 1 << 3 ¿es esto válido? ¿Podría posiblemente entrar en conflicto con los futuros estados de control que apple podría agregar? –

+2

También se debe tener en cuenta; Si planea usar estados personalizados para controlar recursos personalizados en UIButton como el título, la imagen de fondo, la imagen, titleShadow o attributedTitle. Debe llamar a setNeedsLayout después de cambiar su estado personalizado. De lo contrario, el botón solo actualizará su apariencia después de que se toque nuevamente. –

+0

Definitivamente no use el 1 << 3, ya que Adam afirma que entrará en conflicto en futuras versiones del sistema operativo. Use un número en el rango de máscara de bits 0x00FF0000. – christophercotton

5

Basado en @Nick respuesta He implementado una versión más simple. Esta subclase expone una propiedad BOOL outlined que es similar en función a selected, highlighted y enabled.

Hacer cosas como [customButtton setImage:[UIImage imageNamed:@"MyOutlinedButton.png"] forState:UIControlStateOutlined] hace que funcione automágicamente cuando actualiza la propiedad outlined.

Más de estos state + property se pueden agregar si es necesario.


UICustomButton.h

extern const UIControlState UIControlStateOutlined; 

@interface UICustomButton : UIButton 
@property (nonatomic) BOOL outlined; 
@end 

UICustomButton.m

const UIControlState UIControlStateOutlined = (1 << 16); 

@interface OEButton() 
@property UIControlState customState; 
@end 

@implementation OEButton 

- (void)setOutlined:(BOOL)outlined 
{ 
    if (outlined) 
    { 
     self.customState |= UIControlStateOutlined; 
    } 
    else 
    { 
     self.customState &= ~UIControlStateOutlined; 
    } 
    [self stateWasUpdated]; 
} 

- (BOOL)outlined 
{ 
    return (self.customState & UIControlStateOutlined) == UIControlStateOutlined; 
} 

- (UIControlState)state { 
    return [super state] | self.customState; 
} 

- (void)stateWasUpdated 
{ 
    [self setNeedsLayout]; 
} 

// These are only needed if you have additional code on -(void)stateWasUpdated 
// - (void)setSelected:(BOOL)newSelected 
// { 
//  [super setSelected:newSelected]; 
//  [self stateWasUpdated]; 
// } 
// 
// - (void)setHighlighted:(BOOL)newHighlighted 
// { 
//  [super setHighlighted:newHighlighted]; 
//  [self stateWasUpdated]; 
// } 
// 
// - (void)setEnabled:(BOOL)newEnabled 
// { 
//  [super setEnabled:newEnabled]; 
//  [self stateWasUpdated]; 
// } 

@end 
1

Swift la versión 3 de la respuesta de Nick:

extension UIControlState { 
    static let myState = UIControlState(rawValue: 1 << 16) 
} 

class CustomControl: UIControl { 

    private var _customState: UInt = 0 

    override var state: UIControlState { 
     return UIControlState(rawValue: super.state.rawValue | self._customState) 
    } 

    var isMyCustomState: Bool { 
     get { 
      return self._customState & UIControlState.myState.rawValue == UIControlState.myState.rawValue 
     } set { 
      if newValue == true { 
       self._customState |= UIControlState.myState.rawValue 
      } else { 
       self._customState &= ~UIControlState.myState.rawValue 
      } 
     } 
    } 
} 
Cuestiones relacionadas