How to Correctly Subclass Uicontrol

Highlighting a UIControl subclass

I think UIControls automatically set their highlighted property correctly, based solely on touch events. What you need is to override -setHighlighted: method to implement a specific algorithm:

- (void) setHighlighted: (BOOL) highlighted {
[super setHighlighted: highlighted];
// Only as an example. Caution: looks like a disabled control
self.alpha = highlighted ? 0.5f : 1.0f;
}

How to add a listener to a subclass of UIControl

You want your custom control to emit the valueChanged event when the user selects a row in the internal picker view.

Add the line:

sendActions(for: .valueChanged)

where ever you want your custom control to tell all registered targets that the value changed. At a minimum this would be inside your implementation of the pickerView:didSelectRow delegate method.

A few notes:

  • There is no need for you to override addTarget in your custom control other than for debugging purposes.
  • It's strange that you want to use addTarget to be notified when the value changes since your custom control provides the CCDatePickerDelegate delegate protocol.

UIControl -contentHorizontalAlignment: how to use in a subclass

Just to follow up on this...

UIControl just provides these properties as a consistent API for subclasses. The base class doesn't do anything with them.

In your UIControl subclass, override the -layoutSubviews method and use the properties to guide your layout logic.

e.g.

switch (self.contentHorizontalAlignment) {
case UIControlContentHorizontalAlignmentCenter:
// layout logic for centering
break;
}

Custom UIControl subclass set position in IB for iOS

You can drag a UIView onto the nib file, then use the identity inspector (command-opt-3) to change the class to any subclass of UIView.

You will need to set the subclasses in initialization code that gets called when loaded from a nib, i.e. not in initWithFrame:. If you're coding for completeness, both methods (programatic and nib-based) should call the same initialization.

If you like, just create and addSubview: in the initialization code, then implement layoutSubviews to layout your custom subviews. This will be called anytime the view is resized as well as initially.

Custom UIControl subclass with RxSwift

If you are subclassing from UIControl, then you are making your own control class and you have to override one or more of beginTracking(_:with:), continueTracking(_:with:), endTracking(_:with:), or cancelTracking(with:) to make the control work the way you want. Then call sendActions(for:) with the correct event. The guts of a UIControl would not have Rx in it.

Taking a queue from UIButton, your control should not select itself, although it can highlight and unhighlight itself (when the user's finger is on it for example.)

Once you have properly created your UIControl, code outside the control can use Rx to observe it with no extra work on your part.

The following works (Updated for Swift 5/RxSwift 5):

class ViewController: UIViewController {

@IBOutlet weak var yesNoButton: SYYesNoButton!
private let bag = DisposeBag()

override func viewDidLoad() {
super.viewDidLoad()

yesNoButton.rx.controlEvent(.touchUpInside)
.scan(false) { v, _ in !v }
.bind(to: yesNoButton.rx.isSelected)
.disposed(by: bag)
}
}

@IBDesignable
class SYYesNoButton: UIControl {

override func layoutSubviews() {
super.layoutSubviews()
backgroundColor = isSelected ? .green : .red
}

override var isSelected: Bool {
didSet {
super.isSelected = isSelected
backgroundColor = isSelected ? .green : .red
}
}
}


Related Topics



Leave a reply



Submit