有没有办法为UIControlState
设置自定义状态 - 而不是现有的UIControl
值之一?
在UIControlSate
枚举中,有16位可用于自定义控件状态:
UIControlStateApplication = 0x00FF0000, // additional flags available for application use
问题是UIControl
的{{1}}属性只读。
我想为我的state
设置不同的背景图片以用于自定义状态。
答案 0 :(得分:36)
您可以在UIControl的子类中使用自定义状态。
customState
的变量,您可以在其中管理自定义状态。 [self stateWasUpdated]
。 state
媒体资源,以[super state]
customState
enabled
,selected
和highlighted
设置者,以便他们致电[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
答案 1 :(得分:5)
根据@Nick的回答,我实现了一个更简单的版本。此子类公开BOOL outlined
属性,其功能类似于selected
,highlighted
和enabled
。
[customButtton setImage:[UIImage imageNamed:@"MyOutlinedButton.png"] forState:UIControlStateOutlined]
之类的操作会在您更新outlined
属性时自动生效。
如果需要,可以添加更多这些州+属性。
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
答案 2 :(得分:2)
斯威夫特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
}
}
}
}
答案 3 :(得分:2)
我想对该策略进行一些细化。请参阅以下stackoverflow问题:
Overriding isHighlighted still changes UIControlState - why?
事实证明,苹果公司的state
实现实际上是基于其他属性isSelected
,isHighlighted
,isEnabled
等的计算属性。
因此,实际上在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
所表示的属性之间的一致性。