Is there a way to set a custom states -- not one of the existing UIControlState values -- for a UIControl?
In the UIControlSate enum, there are 16 bits that can be used for custom control states:
UIControlStateApplication = 0x00FF0000, // additional flags available for application use The problem is that UIControl's state property is readonly.
I want to set different background images to my UIButton for custom states.
UIControlState() is an "empty" control state with some undocumented default value. It just so happens that both of these are backed with a raw value of 0 . So it seems that both represent the "normal" state. But it is bad practice to rely on this. The defaults could change.
Overview. A control can have more than one state at a time. Controls can be configured differently based on their state. For example, a UIButton object can be configured to display one image when it is in its normal state and a different image when it is highlighted.
You can make use of the custom states in a subclass of UIControl.
customState in which you will manage your custom states. [self stateWasUpdated]. state property to return [super state] bitwise OR'd against your customState enabled, selected and highlighted setters so that they call [self stateWasUpdated]. This will allow you to respond to any changes in state, not just changes to customState stateWasUpdated with logic to respond to changes in stateIn the header:
#define kUIControlStateCustomState (1 << 16) @interface MyControl : UIControl { UIControlState customState; } In the implementation:
@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
Based on @Nick answer I have implemented a simpler version. This subclass exposes a BOOL outlined property that is similar in function to selected, highlighted and enabled.
Doing things like [customButtton setImage:[UIImage imageNamed:@"MyOutlinedButton.png"] forState:UIControlStateOutlined] makes it automagically work when you update the outlined property.
More of these state + property could be added if needed.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With