Reputation: 1439
I have the following UIButton to render a checkbox and label;
To create this, I used a UIButton control with an NSMutableAttributedString
to give "Terms & Conditions" a different style to the rest of the text.
Just like with a checkbox on a web page, I want the user to be able to tap either the grey text or the image itself to toggle the checkbox on or off.
But if the user clicks "Terms & Conditions" I want that to perform an action (e.g. load a terms URL).
This is really easy to do in Android as you can use checkbox.setMovementMethod(LinkMovementMethod.getInstance());
, but in iOS I'm really struggling to find a way to basically create a checkbox with a label that contains a link.
Has anyone ever done this before and how did you approach?
Upvotes: 0
Views: 1767
Reputation: 1439
I ended up doing the following;
Created a UIButton (empty text label) for my actual checkbox and a UITextView for my adjacent checkbox label text.
I then used NSMutableAttributedString
like so;
class MyViewController: UIViewController, UITextViewDelegate {
override func viewDidLoad() {
let attributedTermsTitle = NSMutableAttributedString()
attributedTermsTitle.append(NSAttributedString(string: "I have read and accept the ", attributes: [NSFontAttributeName:UIFont(name: "My-Font", size: 14)!]))
attributedTermsTitle.append(NSAttributedString(string: "Terms & Conditions", attributes: [NSFontAttributeName:UIFont(name: "My-Font", size: 14)!, NSLinkAttributeName: "terms"]))
termsText.linkTextAttributes = [NSForegroundColorAttributeName: UIColor.blue]
termsText.attributedText = attributedTermsTitle
termsText.delegate = self
termsText.isSelectable = true
termsText.isUserInteractionEnabled = true
termsText.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(MyViewController.toggleCheckbox)))
}
func toggleCheckbox(sender: UITapGestureRecognizer) {
termsButton.isChecked = !termsButton.isChecked
}
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
let link = URL.absoluteString
if(link == "terms") {
// link to the Terms web page / screen
}
return false
}
}
and for the UIButton, gave the class;
class CheckBox: UIButton {
let checkedImage = UIImage(named: "checkbox_on")! as UIImage
let uncheckedImage = UIImage(named: "checkbox_off")! as UIImage
var isChecked: Bool = false {
didSet{
if isChecked == true {
self.setImage(checkedImage, for: UIControlState.normal)
} else {
self.setImage(uncheckedImage, for: UIControlState.normal)
}
}
}
override func awakeFromNib() {
self.addTarget(self, action:#selector(buttonClicked(sender:)), for: UIControlEvents.touchUpInside)
self.isChecked = false
}
func buttonClicked(sender: UIButton) {
if sender == self {
isChecked = !isChecked
}
}
}
End result is that both the UIButton and the non-linked text of the UITextView will toggle the checkbox on and off. The "Terms & Conditions" text will link to the website or segue somewhere else.
Hopefully this helps someone else out.
Upvotes: 4
Reputation: 2714
You can use TTTAttributedLabel to make a particular part or word tappable in a UILabel.
For example
label.text = @"Fork me on GitHub!"; // Repository URL will be automatically detected and linked
NSRange range = [label.text rangeOfString:@"me"];
[label addLinkToURL:[NSURL URLWithString:@"meUrl"] withRange:range];
Here me becomes tappable and on tapping that word delegate method didSelectLinkWithURL gets called and you can check for that link inside that function
(void)attributedLabel:(TTTAttributedLabel *)label didSelectLinkWithURL:(NSURL *)url {
NSLog(@"link %@", [url absoluteString]);
if ([url absoluteString] == @"meUrl") {
//implement your logic here
}
NSLog(@"whole label %@", label);
}
Upvotes: 1