处理同一个分段按钮上的点击?
Handle tap on same segmented button?
我正在尝试处理分段控件上的点击事件,但是当再次单击所选按钮时。例如,对于下面已选择 "Second" 的屏幕截图,再次单击 "Second" 按钮时如何处理该操作?
我尝试了 IBOutlet
,但它仅在值更改时触发。然后我尝试了下面的代码,但同样的事情只在值改变时触发。在这两种情况下,当 "Second" 被选中时,再次单击 "Second" 不会触发任何东西。有办法吗?
segmentedControl.addTarget(self, action: "segementedAnyTap:", forControlEvents: .AllEvents)
在您对问题的评论中,您提到您试图允许用户 select 'unread' 显示所有未读消息,然后让他们再次单击以将所有消息标记为未读。我建议不要为此使用段控件,而是添加一个 "Mark all unread" 按钮,该按钮会在 'unread' 段被 selected 时出现。这将完成您尝试添加的功能,同时也让用户清楚他们有办法将所有内容标记为未读。
这对我有用,将手势识别器添加到 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
}
您可以将您的应用程序设置为显示来自未读片段的弹出窗口,并带有一个按钮以将所有片段显示为未读。要放置弹出窗口,请使用:
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];
我不太清楚你为什么要实现这个,但我想建议继承 UISegmentedControl
并覆盖 touchesEnded:withEvent:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
}
现在,您为 UIControlEventTouchUpInside
预定的选择器将在您每次按下每个段时被调用,并且仍然保留 UISegmentedControl
的默认功能。
注意:如果这是段的第一个选择,您需要自己处理(例如,保留先前值的私有 属性)。如果您为 UIControlEventValueChanged
添加选择器,它也会触发 UIControlEventTouchUpInside
的选择器,这可能会导致一些混乱或错误。
祝你好运,希望对你有所帮助。
我认为这可以解决问题:
- (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];
}
添加 KVO 观察。
例子:
#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
我对具有 3 个选项 ("categories") 的分段控件执行以下操作。 _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...
}
}
}
我知道有点晚了,但是另一种对我很有效的技术...
在 UISegmentedControl 的每个部分上添加一个背景清晰的 UIButton。每个 UIButton 都可以有自己的 UIControlEventTouchUpInside 事件处理程序——它可以更改 UISegmentedControl 的 selectedSegmentIndex。
然后将 UISegmentedControl.userInteractionEnabled 设置为 NO,并删除其 UIControlEventValueChanged 事件处理程序。
很好的答案@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
}
我遇到一个情况,在选择之前我需要段索引,我不希望 .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
}
我正在尝试处理分段控件上的点击事件,但是当再次单击所选按钮时。例如,对于下面已选择 "Second" 的屏幕截图,再次单击 "Second" 按钮时如何处理该操作?
我尝试了 IBOutlet
,但它仅在值更改时触发。然后我尝试了下面的代码,但同样的事情只在值改变时触发。在这两种情况下,当 "Second" 被选中时,再次单击 "Second" 不会触发任何东西。有办法吗?
segmentedControl.addTarget(self, action: "segementedAnyTap:", forControlEvents: .AllEvents)
在您对问题的评论中,您提到您试图允许用户 select 'unread' 显示所有未读消息,然后让他们再次单击以将所有消息标记为未读。我建议不要为此使用段控件,而是添加一个 "Mark all unread" 按钮,该按钮会在 'unread' 段被 selected 时出现。这将完成您尝试添加的功能,同时也让用户清楚他们有办法将所有内容标记为未读。
这对我有用,将手势识别器添加到 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
}
您可以将您的应用程序设置为显示来自未读片段的弹出窗口,并带有一个按钮以将所有片段显示为未读。要放置弹出窗口,请使用:
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];
我不太清楚你为什么要实现这个,但我想建议继承 UISegmentedControl
并覆盖 touchesEnded:withEvent:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
}
现在,您为 UIControlEventTouchUpInside
预定的选择器将在您每次按下每个段时被调用,并且仍然保留 UISegmentedControl
的默认功能。
注意:如果这是段的第一个选择,您需要自己处理(例如,保留先前值的私有 属性)。如果您为 UIControlEventValueChanged
添加选择器,它也会触发 UIControlEventTouchUpInside
的选择器,这可能会导致一些混乱或错误。
祝你好运,希望对你有所帮助。
我认为这可以解决问题:
- (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];
}
添加 KVO 观察。
例子:
#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
我对具有 3 个选项 ("categories") 的分段控件执行以下操作。 _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...
}
}
}
我知道有点晚了,但是另一种对我很有效的技术...
在 UISegmentedControl 的每个部分上添加一个背景清晰的 UIButton。每个 UIButton 都可以有自己的 UIControlEventTouchUpInside 事件处理程序——它可以更改 UISegmentedControl 的 selectedSegmentIndex。
然后将 UISegmentedControl.userInteractionEnabled 设置为 NO,并删除其 UIControlEventValueChanged 事件处理程序。
很好的答案@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
}
我遇到一个情况,在选择之前我需要段索引,我不希望 .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
}