我正在尝试处理分段控件上的点击事件,但是再次单击所选按钮时。例如,对于下面已选择“秒”的屏幕截图,如何再次单击“第二个”按钮时如何处理操作?
我尝试了IBOutlet
,但只在值发生变化时触发。然后我尝试了下面的代码,但是只有在值发生变化时它才触发。在两种情况下,选择“秒”时,再次单击“秒”不会触发任何内容。有没有办法做到这一点?
segmentedControl.addTarget(self, action: "segementedAnyTap:", forControlEvents: .AllEvents)
答案 0 :(得分:6)
这适用于我,为UISegmentedControl添加手势识别器
- (void)viewDidLoad
{
[super viewDidLoad];
[self.segmentedControl addTarget:self action:@selector(valueChanged:) forControlEvents:UIControlEventValueChanged];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(touched:)];
[self.segmentedControl addGestureRecognizer:tapGesture];
}
- (void)valueChanged:(id)sender
{
// value change code
}
- (void)touched:(id)sender
{
// code to check if the segmented controls index has not changed.
// execute desired functionality
}
答案 1 :(得分:4)
很棒的答案@Sgorbyo,这是它的Swift 3版本:
override func viewDidLoad() {
super.viewDidLoad()
let segmentedTapGesture = UITapGestureRecognizer(target: self, action: #selector(onTapGestureSegment(_:)))
segmentedControl.addGestureRecognizer(segmentedTapGesture)
}
@IBAction func onTapGestureSegment(_ tapGesture: UITapGestureRecognizer) {
let point = tapGesture.location(in: segmentedControl)
let segmentSize = tipSegmentedControl.bounds.size.width / CGFloat(segmentedControl.numberOfSegments)
let touchedSegment = Int(point.x / segmentSize)
if segmentedControl.selectedSegmentIndex != touchedSegment {
// Normal behaviour the segment changes
segmentedControl.selectedSegmentIndex = touchedSegment
} else {
// Tap on the already selected segment
segmentedControl.selectedSegmentIndex = touchedSegment
}
onSegment(segmentedControl)
}
@IBAction func onSegment(_ sender: Any) {
// Your segment changed selector
}
答案 2 :(得分:2)
我认为这可以解决问题:
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(touched:)];
[self.segmentedControl addGestureRecognizer:tapGesture];
}
- (void) valueChanged:(id) sender {
// Your segment changed selector
}
- (void) touched:(UITapGestureRecognizer *) tapGesture {
CGPoint point = [tapGesture locationInView:self.segmentedControl];
NSUInteger segmentSize = self.segmentedControl.bounds.size.width / self.segmentedControl.numberOfSegments;
// Warning: If you are using segments not equally sized, you have to adapt the code in the next line
NSUInteger touchedSegment = point.x / segmentSize;
if (self.segmentedControl.selectedSegmentIndex != touchedSegment) {
// Normal behaviour the segment changes
self.segmentedControl.selectedSegmentIndex = touchedSegment;
} else {
// Tap on the already selected segment, I'm switching to No segment selected just to show the effect
self.segmentedControl.selectedSegmentIndex = UISegmentedControlNoSegment;
}
// You have to call your selector because the UIControlEventValueChanged can't work together with UITapGestureRecognizer
[self valueChanged:self.segmentedControl];
}
答案 3 :(得分:2)
添加KVO观察。
的exaple:
#pragma mark -
- (void)viewDidLoad {
[_segmentControl addObserver:self forKeyPath:@"selectedSegmentIndex" options:NSKeyValueObservingOptionInitial context:nil];
}
#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
NSLog(@"segment index: %ld", (long)_segmentControl.selectedSegmentIndex);
}
结果:
2015-06-22 12:31:54.155 Location test[27082:13176230] segment index: 0
2015-06-22 12:31:54.740 Location test[27082:13176230] segment index: 0
2015-06-22 12:31:55.821 Location test[27082:13176230] segment index: 1
2015-06-22 12:31:56.529 Location test[27082:13176230] segment index: 1
答案 4 :(得分:1)
我不太确定你为什么试图实现这个目标,但我想建议继承UISegmentedControl
并覆盖touchesEnded:withEvent:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
}
现在,每次按下每个细分时,系统都会调用UIControlEventTouchUpInside
的预定选择器,并保持UISegmentedControl
的默认功能。
注意:如果这是段的第一个选择(例如保留前一个值的私有属性),则需要自己处理。如果您为UIControlEventValueChanged
添加选择器,它也会触发UIControlEventTouchUpInside
的选择器,这可能会引起一些混乱或错误。
祝你好运,希望有所帮助。
答案 5 :(得分:1)
我为具有3个选项(“类别”)的分段控件执行以下操作。 _selectedCategory
是一个属性NSInteger
,用于跟踪当前所选索引的分段控件。点击,如果我发现_selectedCategory
与按下的 -(IBAction)categorySelected:(id)sender {
if (_selectedCategory == [sender selectedSegmentIndex]) {
sender.selectedSegmentIndex = UISegmentedControlNoSegment;
// update my model, etc...
} else {
_selectedCategory = [sender selectedSegmentIndex];
switch (_selectedCategory) {
case 0:
// do logic...
}
}
}
相同,则按下所选的分段控件并将其关闭。
{{1}}
答案 6 :(得分:0)
在您对自己问题的评论中,您提到了您尝试允许用户选择“未读”的问题。要显示所有未读邮件,请再次单击以将所有邮件标记为未读。我建议不要使用分段控件来添加"标记所有未读" “未读”时出现的按钮'细分已被选中。这将完成您尝试添加的功能,同时还向用户明确说明他们有办法将所有内容标记为未读。
答案 7 :(得分:0)
您可以将应用设置为显示来自未读片段的弹出窗口,其中包含一个按钮,将所有片段显示为未读。要放置弹出窗口,请使用:
CGRect frame = [segmentControl frame];
frame =CGRectMake((frame.size.width/2*butIndex), 0, frame.size.width/2, segmentControl.bounds.size.height);
[popOver presentPopoverFromRect:frame inView:segmentControl permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
答案 8 :(得分:0)
我知道的有点晚了,但另一项对我有用的技术......
在UISegmentedControl的每个段上添加一个背景清晰的UIButton。每个UIButton都可以拥有自己的UIControlEventTouchUpInside事件处理程序 - 它可以更改UISegmentedControl的selectedSegmentIndex。
然后将UISegmentedControl.userInteractionEnabled设置为NO,并删除其UIControlEventValueChanged事件处理程序。
答案 9 :(得分:0)
我遇到一个在选择之前需要段索引的情况,并且我不希望.valueChanged
事件停止触发,因此我想出了这一点。
为UISegmentedControl
创建一个子类并覆盖touchesEnded
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
// Previous selected segment index
let oldIdx = selectedSegmentIndex
super.touchesEnded(touches, with: event)
// New selected segment index
let newIdx = selectedSegmentIndex
// If the previously selected segment index is equal to the new one,
// then you are tapping on the same segment button.
// Call a block, delegate method or whatever to notify this
}