我可以使用UIControlState的自定义值来控制自己吗?

有没有办法为UIControlState设置自定义状态 – 不是现有的UIControlState值之一?

UIControlSate枚举中,有16位可用于自定义控件状态:

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

问题是UIControlstate属性是只读的

我想为我的UIButton设置不同的背景图像以用于自定义状态。

您可以在UIControl的子类中使用自定义状态。

  • 创建一个名为customState的变量,您可以在其中管理自定义状态。
  • 如果需要设置状态,请对此变量执行标志操作,并调用[self stateWasUpdated]
  • 覆盖state属性以针对customState按位返回[super state]
  • 覆盖已enabled ,已selectedhighlighted setter,以便它们调用[self stateWasUpdated] 。 这将允许您响应状态的任何更改,而不仅仅是对customState更改
  • 使用逻辑实现stateWasUpdated以响应状态的变化

在标题中:

 #define kUIControlStateCustomState (1 << 16) @interface MyControl : UIControl { UIControlState customState; } 

在实施中:

 @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 

根据@Nick的回答,我实现了一个更简单的版本。 此子类公开BOOL outlined属性,该属性在function上类似于selectedhighlightedenabled

[customButtton setImage:[UIImage imageNamed:@"MyOutlinedButton.png"] forState:UIControlStateOutlined]做会使你在更新[customButtton setImage:[UIImage imageNamed:@"MyOutlinedButton.png"] forState:UIControlStateOutlined]属性时自动运行。

如果需要,可以添加更多这些州+财产


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 

斯威夫特3版尼克的回答:

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

我想对这个策略稍作改进。 请参阅此stackoverflow问题:

覆盖是突出显示还是会改变UIControlState – 为什么?

事实certificate,Apple的state实现实际上是一个基于其他属性的计算属性, isSelectedisHighlightedisEnabled等。

因此,在UIControlState之上实际上不需要自定义状态位掩码(嗯,并不是没有必要,只是它在需要/不应该的地方增加了复杂性)。

如果你想与Apple的实现一致,你只需覆盖state属性并检查getter中的自定义状态。

 extension UIControlState { static let myState = UIControlState(rawValue: 1 << 16) } class MyControl: UIControl { override var state: UIControlState { var state = super.state if self.isMyCustomState { state.insert(UIControlState.myState) } return state } var isMyCustomState: Bool = false } 

这实际上是一种聪明的方式; 根据上面的链接,如果您覆盖该属性并且不更改状态,您将得到不一致的结果。 使状态始终是计算属性可确保state表示的属性之间的一致性。