如何永久取消选择“分段控制”按钮中的某个段,直到再次单击它为止 [英] How to deselect a segment in Segmented control button permanently till its clicked again
问题描述
我有一个 UISegmentedControl
,有4个段。选择它后,它应该保持选择状态
。再次单击同一段时,应取消选择
。
如何实现这个目标?
I have a UISegmentedControl
with 4 segments. When it is selected, it should maintain the selected state
. When the same segment is clicked again, it should deselect itself
.
How to achieve this?
推荐答案
仅限 UISegmentedControl
如果选择了未选择的段,则发送操作,您必须继承 UISegmentedControl
以对其触摸处理进行微小更改。我使用这个类:
Since UISegmentedControl
only sends an action if a not selected segment is selected, you have to subclass UISegmentedControl
to make a tiny change in its touch handling. I use this class:
@implementation MBSegmentedControl
// this sends a value changed event even if we reselect the currently selected segment
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSInteger current = self.selectedSegmentIndex;
[super touchesBegan:touches withEvent:event];
if (current == self.selectedSegmentIndex) {
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
}
@end
现在即使已经选择了段,您也将获得 UIControlEventValueChanged
事件。只需将当前索引保存在变量中并在操作中进行比较即可。如果两个索引匹配,则必须取消选择触摸的段。
Now you will get UIControlEventValueChanged
events even if the segment is already selected. Simply save the current index in a variable and compare it in the action. If the two indexes match you have to unselect the touched segment.
// _selectedSegmentIndex is an instance variable of the view controller
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
_selectedSegmentIndex = self.segment.selectedSegmentIndex;
}
- (IBAction)segmentChanged:(UISegmentedControl *)sender {
if (sender.selectedSegmentIndex == _selectedSegmentIndex) {
NSLog(@"Segment %d deselected", sender.selectedSegmentIndex);
sender.selectedSegmentIndex = UISegmentedControlNoSegment;
_selectedSegmentIndex = UISegmentedControlNoSegment;
}
else {
NSLog(@"Segment %d selected", sender.selectedSegmentIndex);
_selectedSegmentIndex = sender.selectedSegmentIndex;
}
}
iOS 7改变了UISegmentedControl处理触摸的方式。现在,在 touchesEnded:
期间,selectedSegmentIndex已更改。
iOS 7 changed how touches are handled for UISegmentedControl. The selectedSegmentIndex is now changed during touchesEnded:
.
因此更新后的子类应如下所示:
So the updated Subclass should look like this:
@implementation MBSegmentedControl
+ (BOOL)isIOS7 {
static BOOL isIOS7 = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSInteger deviceSystemMajorVersion = [[[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."] objectAtIndex:0] integerValue];
if (deviceSystemMajorVersion >= 7) {
isIOS7 = YES;
}
else {
isIOS7 = NO;
}
});
return isIOS7;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSInteger previousSelectedSegmentIndex = self.selectedSegmentIndex;
[super touchesBegan:touches withEvent:event];
if (![[self class] isIOS7]) {
// before iOS7 the segment is selected in touchesBegan
if (previousSelectedSegmentIndex == self.selectedSegmentIndex) {
// if the selectedSegmentIndex before the selection process is equal to the selectedSegmentIndex
// after the selection process the superclass won't send a UIControlEventValueChanged event.
// So we have to do this ourselves.
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSInteger previousSelectedSegmentIndex = self.selectedSegmentIndex;
[super touchesEnded:touches withEvent:event];
if ([[self class] isIOS7]) {
// on iOS7 the segment is selected in touchesEnded
if (previousSelectedSegmentIndex == self.selectedSegmentIndex) {
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
}
}
@end
Swift 2.2版本,解决了Grzegorz注意到的问题。
Swift 2.2 version, fixed the problem Grzegorz noticed.
class ReselectableSegmentedControl: UISegmentedControl {
@IBInspectable var allowReselection: Bool = true
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
let previousSelectedSegmentIndex = self.selectedSegmentIndex
super.touchesEnded(touches, withEvent: event)
if allowReselection && previousSelectedSegmentIndex == self.selectedSegmentIndex {
if let touch = touches.first {
let touchLocation = touch.locationInView(self)
if CGRectContainsPoint(bounds, touchLocation) {
self.sendActionsForControlEvents(.ValueChanged)
}
}
}
}
}
Swift 3.0更改此修复程序如下所示:
Swift 3.0 changes the fix for this to look like the following:
class MyDeselectableSegmentedControl: UISegmentedControl {
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
let previousIndex = selectedSegmentIndex
super.touchesEnded(touches, with: event)
if previousIndex == selectedSegmentIndex {
let touchLocation = touches.first!.location(in: self)
if bounds.contains(touchLocation) {
sendActions(for: .valueChanged)
}
}
}
}
这篇关于如何永久取消选择“分段控制”按钮中的某个段,直到再次单击它为止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!