28

UIControlStateのカスタム状態(既存の値の1つではない)を設定する方法はありUIControlますか?

列挙型には、UIControlSateカスタム制御状態に使用できる16ビットがあります。

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

問題は、UIControlstateプロパティが読み取り専用であるということです。

UIButtonカスタム状態用に別の背景画像を設定したい。

4

4 に答える 4

36

UIControlのサブクラスでカスタム状態を利用できます。

  • customStateカスタム状態を管理する という変数を作成します。
  • 状態を設定する必要がある場合は、この変数に対してフラグ操作を実行し、を呼び出します[self stateWasUpdated]
  • stateプロパティをオーバーライドして、[super state]ビット単位のORを返します。customState
  • enabledselectedおよび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
于 2011-01-18T14:25:52.093 に答える
6

@Nickの回答に基づいて、より単純なバージョンを実装しました。このサブクラスは、関数が、、およびBOOL outlinedに類似しているプロパティを公開します。selectedhighlightedenabled

このようなことを行うと、プロパティ[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
于 2014-07-15T12:39:25.777 に答える
3

この戦略を少し改良したいと思います。このstackoverflowの質問を参照してください:

isHighlightedをオーバーライドしてもUIControlStateは変更されます-なぜですか?

Appleのstate実装は、実際には他のプロパティ、、、などに基づいて計算されたプロパティであることがisSelectedわかりisHighlightedますisEnabled

したがって、実際にはUIControlStateの上にカスタム状態ビットマスクは必要ありません(必要がないというわけではありません。必要がある/必要がない場所に複雑さを追加しているだけです)。

Appleの実装と一致したい場合は、stateプロパティをオーバーライドし、ゲッターでカスタム状態を確認するだけです。

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表すプロパティ間の一貫性が保証されます。

于 2018-08-13T18:40:51.607 に答える
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
            }
        }
    }
}
于 2017-06-12T00:33:14.483 に答える