UISegmentedControl 레지스터는 선택한 세그먼트를 탭합니다.
사용자가 목록을 주문하는 방법을 선택할 수있는 세그먼트 화 된 컨트롤이 있습니다. 잘 작동합니다.
그러나 이미 선택한 세그먼트를 탭하면 순서가 반전되기를 바랍니다. 모든 코드가 제자리에 있지만 해당 세그먼트에 탭을 등록하는 방법을 모르겠습니다. 사용할 수있는 유일한 제어 이벤트는 UIControlEventValueChanged 인 것 같지만 작동하지 않습니다 (선택한 세그먼트가 실제로 변경되지 않기 때문에).
이에 대한 해결책이 있습니까? 그렇다면 그것은 무엇입니까?
미리 감사드립니다!
하위 클래스 UISegmentedControl
를 만든 다음override setSelectedSegmentIndex:
- (void) setSelectedSegmentIndex:(NSInteger)toValue {
if (self.selectedSegmentIndex == toValue) {
[super setSelectedSegmentIndex:UISegmentedControlNoSegment];
} else {
[super setSelectedSegmentIndex:toValue];
}
}
IB를 사용하는 경우 클래스를 UISegmentedControl
하위 클래스로 설정했는지 확인하십시오 .
이제 UIControlEventValueChanged
사용자가 세그먼트를 선택 취소 한 경우를 제외하고는 평소와 selectedSegmentIndex
동일하게들을 수 있습니다 UISegmentedControlNoSegment
.
-(IBAction) valueChanged: (id) sender {
UISegmentedControl *segmentedControl = (UISegmentedControl*) sender;
switch ([segmentedControl selectedSegmentIndex]) {
case 0:
// do something
break;
case 1:
// do something
break;
case UISegmentedControlNoSegment:
// do something
break;
default:
NSLog(@"No option for: %d", [segmentedControl selectedSegmentIndex]);
}
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
UISegmentedControl의 동작이므로 --- 사용하면 조금 더 좋습니다 . 또한 과부하가 필요하지 않은 것 같습니다.-(void)setSelectedSegmentIndex:(NSInteger)toValue
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSInteger current = self.selectedSegmentIndex;
[super touchesBegan:touches withEvent:event];
if (current == self.selectedSegmentIndex)
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
이것을 직접 원했습니다. Julian의 해결책을 취하고 (감사합니다!) 약간 수정되었습니다.
다음 UISegmentedControl 하위 클래스 UIControlEventValueChanged
는 값이 변경되지 않은 경우에도 이벤트 를 트리거합니다 . 이는 분명히 약간 이상하게 읽지 만 제 경우에는 잘 작동하고 일을 간단하게 유지합니다.
AKSegmentedControl.h
#import <UIKit/UIKit.h>
@interface AKSegmentedControl : UISegmentedControl {
}
@end
AKSegmentedControl.m
#import "AKSegmentedControl.h"
@implementation AKSegmentedControl
- (void)setSelectedSegmentIndex:(NSInteger)toValue {
// Trigger UIControlEventValueChanged even when re-tapping the selected segment.
if (toValue==self.selectedSegmentIndex) {
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
[super setSelectedSegmentIndex:toValue];
}
@end
이것은 iOS 4 및 5 모두에서 작동합니다.
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
int oldValue = self.selectedSegmentIndex;
[super touchesBegan:touches withEvent:event];
if ( oldValue == self.selectedSegmentIndex )
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
실제로 새 세그먼트를 탭하지 않는 한 setSelectedSegmentIndex가 호출되지 않기 때문에 현재 제시된 솔루션은 여전히 작동하지 않습니다. 적어도 내 경우에는 이것이 효과가 없었지만 iOS5를 사용하지만 아마도이 솔루션은 iOS4에서 작동했을 것입니다. 어쨌든 이것은 내 해결책입니다. 다음과 같은 추가 하위 클래스 메서드가 하나 필요합니다.
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self setSelectedSegmentIndex:self.selectedSegmentIndex];
[super touchesEnded:touches withEvent:event];
}
행운을 빕니다!
이것은 꽤 오래된 질문이어서 iOS 5+ 앱에서이 문제를 접했을 때 사용한 다소 간단한 솔루션을 추가 할 것이라고 생각했습니다.
내가 한 것은 탭 제스처 인식기를 .xib 파일의 UISegmentedControl로 드래그하는 것뿐이었습니다. 새 제스처 인식기의 연결을 확인하여 세그먼트 화 된 컨트롤이 유일한 gestureRecognizer 콘센트인지 확인한 다음 해당 동작을 컨트롤러에서 실행하려는 메서드에 연결하면됩니다.
이 메서드는 세그먼트 화 된 컨트롤을 터치 할 때마다 실행되어야하므로 인스턴스 변수를 사용하여 선택한 인덱스를 확인하여 사용자가 이미 선택한 세그먼트를 터치했는지 확인합니다.
@implementation MyViewController
@synthesize selectedSegment;
@synthesize segmentedControl;
// connected to Tap Gesture Recognizer's action
- (IBAction)segmentedControlTouched:(id)sender
{
NSLog(@"Segmented Control Touched");
if (selectedSegment == [segmentedControl selectedSegmentIndex]) {
// Do some cool stuff
}
selectedSegment = [segmentedControl selectedSegmentIndex];
}
@end
iOS8에서 모든 답변은 작동하지 않거나 변경을 두 번 트리거하는 것 같습니다. 저는 아주 간단한 해결책을 생각해 냈습니다. 그래서 그것을 공유하고 싶습니다.
하위 클래스에서는 다음 만 있습니다.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
[self setSelectedSegmentIndex:UISegmentedControlNoSegment];
}
그것이하는 일은 세그먼트 화 된 제어 세그먼트를 변경하기 전에 선택된 세그먼트를 -1로 재설정하는 것입니다. touchesEnded 메서드에서 발생합니다.
이것은 작동합니다 :
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
int oldValue = self.selectedSegmentIndex;
[super touchesBegan:touches withEvent:event];
if (oldValue == self.selectedSegmentIndex)
{
[super setSelectedSegmentIndex:UISegmentedControlNoSegment];
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
}
Swift 3 에서는 다음과 같이 적어도 두 가지 솔루션을 상상할 수 있습니다. 특별한 경우를 위해 선택한 세그먼트가 토글 버튼으로 작동하는 세 번째 솔루션도 게시했습니다.
해결책 1 :
힌트 :이 솔루션은 순간적인 controlSegments에서만 작동합니다! 고정 제어에 대한 솔루션이 필요하면 솔루션 2를 선택하십시오.
아이디어는 터치 업 내부에서 발생하는 두 번째 이벤트를 등록하는 것입니다.
// this solution works only for momentary segment control:
class Solution1ViewController : UIViewController {
var current:Int = UISegmentedControlNoSegment
@IBOutlet weak var mySegmentedControl: UISegmentedControl! {
didSet {
guard mySegmentedControl != nil else { return }
self.mySegmentedControl!.addTarget(
self,
action:#selector(changeSelection(sender:)),
for: .valueChanged)
self.mySegmentedControl!.addTarget(
self,
action:#selector(changeSelection(sender:)),
for: .touchUpInside)
}
}
func changeSelection(sender: UISegmentedControl) {
if current == sender.selectedSegmentIndex {
// user hit the same button again!
print("user hit the same button again!")
}
else {
current = sender.selectedSegmentIndex
// user selected a new index
print("user selected a new index")
}
}
}
해결 방법 2 : 다른 방법으로 터치 기능을 무시하는 것입니다 UISegmentedControl
과 화재 valueChanged
세그먼트 인덱스가 변경되지 않은 경우에도 마찬가지입니다. 따라서 UISegmentedControl
다음과 같이 재정의 할 수 있습니다 .
// override UISegmentControl to fire event on second hit:
class Solution2SegmentControl : UISegmentedControl
{
private var current:Int = UISegmentedControlNoSegment
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
current = self.selectedSegmentIndex
super.touchesBegan(touches, with: event)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
if current == self.selectedSegmentIndex {
self.sendActions(for: .valueChanged)
}
}
}
// solution2 works with stationary (default) segment controls
class Solution2ViewController : UIViewController {
var current:Int = UISegmentedControlNoSegment
@IBOutlet weak var mySegmentedControl: UISegmentedControl! {
didSet {
guard mySegmentedControl != nil else { return }
self.mySegmentedControl!.addTarget(
self,
action:#selector(changeSelection(sender:)),
for: .valueChanged)
}
}
func changeSelection(sender: UISegmentedControl) {
if current == sender.selectedSegmentIndex {
// user hit the same button again!
print("user hit the same button again!")
}
else {
current = sender.selectedSegmentIndex
// user selected a new index
print("user selected a new index")
}
}
}
솔루션 3 : 접근 방식이 선택한 세그먼트를 토글 버튼으로 사용하는 것이라면 솔루션 2를 변경하여 다음과 같이 코드를 정리할 수 있습니다.
class MyToggleSegmentControl : UISegmentedControl {
/// you could enable or disable the toggle behaviour here
var shouldToggle:Bool = true
private var current:Int = UISegmentedControlNoSegment
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
current = self.selectedSegmentIndex
super.touchesBegan(touches, with: event)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
if shouldToggle, current == self.selectedSegmentIndex {
self.selectedSegmentIndex = UISegmentedControlNoSegment
}
}
}
이제 changeSelection
다음과 같이 함수를 정리할 수 있습니다.
func changeSelection(sender: UISegmentedControl) {
switch sender.selectedSegmentIndex {
case UISegmentedControlNoSegment:
print("none")
default:
print("selected: \(sender.selectedSegmentIndex)")
}
}
여기 내 해결책이 있습니다. ValueChanged 이벤트가 모든 터치에서 발생하기를 원한다면 가장 우아한 것입니다 ...
.h
@interface UISegmentedControlAllChanges : UISegmentedControl
@end
.미디엄
@implementation UISegmentedControlAllChanges
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self sendActionsForControlEvents:UIControlEventValueChanged];
[super touchesEnded:touches withEvent:event];
}
@end
내가 가진 첫 번째 아이디어는 Touch Up Inside
또는 Touch Down
작업을 정렬 방법에 연결하는 것이었지만 이것은 작동하지 않는 것 같습니다.
두 번째 아이디어는 Momentary
분할 된 컨트롤에 속성을 설정하는 것 입니다. 그러면 Value Did Change
탭할 때마다 액션이 실행됩니다.
큰 도움! 내가 원하는 것은 하나의 버튼을 설정하거나 설정하지 않는 옵션이 있으며 버튼이 설정되면 두 번째 탭으로 설정이 해제됩니다. 이것은 내 수정입니다.
- (void)setSelectedSegmentIndex:(NSInteger)toValue
{
// Trigger UIControlEventValueChanged even when re-tapping the selected segment.
if (toValue==self.selectedSegmentIndex) {
[super setSelectedSegmentIndex:UISegmentedControlNoSegment]; // notify first
[self sendActionsForControlEvents:UIControlEventValueChanged]; // then unset
} else {
[super setSelectedSegmentIndex:toValue];
}
}
먼저 알림을 사용하면 컨트롤을 읽고 재설정하기 전에 현재 설정을 찾을 수 있습니다.
Bob de Graaf의 답변을 바탕으로 :
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self sendActionsForControlEvents:UIControlEventAllTouchEvents];
[super touchesEnded:touches withEvent:event];
}
사용 주 UIControlEventAllTouchEvents
대신을 UIControlEventValueChanged
.
또한를 호출 할 필요가 없습니다 -(void)setSelectedSegmentIndex:
.
나를 위해 일한 코드 아래. 같은 세그먼트를 반복해서 탭하면 선택이 해제됩니다.
@implementation WUUnselectableSegmentedControl
{
NSUInteger _selectedIndexBeforeTouches;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
_selectedIndexBeforeTouches = self.selectedSegmentIndex;
[super touchesBegan:touches withEvent:event];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
if (_selectedIndexBeforeTouches == self.selectedSegmentIndex)
{
// Selection didn't change after touch - deselect
self.selectedSegmentIndex = UISegmentedControlNoSegment;
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
}
@end
iOS 9 솔루션. UISegmentedControl을 다음 클래스로 재정의합니다.
@interface SegmentedControl()
@property (nonatomic) NSInteger previousCurrent;
@end
@implementation SegmentedControl
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
self.previousCurrent = self.selectedSegmentIndex;
[super touchesBegan:touches withEvent:event];
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
if (self.selectedSegmentIndex == self.previousCurrent) {
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
self.previousCurrent = NSNotFound;
}
@end
대답하기에 재미있는 질문처럼 보입니다. 이 계획은 Steve E와 yershuachu의 솔루션을 확장합니다. 이 버전은 UITapGestureRecognizer를 사용하여 모든 터치를 캡처하고 selectedSegmentIndex를 -1로 설정합니다. 그러나 모든 터치를 UISegmentedControl에 전달하므로 모든 일반 터치를 처리 할 수 있습니다. 하위 분류가 필요하지 않습니다.
UISegmentedControl *mySegControl;
- (void)viewDidLoad
{
[super viewDidLoad];
[mySegControl addTarget:self action:@selector(segmentAction:)
forControlEvents:UIControlEventValueChanged];
// allow the a seg button tap to be seen even if already selected
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(unitsSegTap:)];
tapGesture.cancelsTouchesInView = NO; // pass touches through for normal taps
[mySegControl addGestureRecognizer:tapGesture];
// continue setup ...
}
- (void)segTap:(UITapGestureRecognizer *)sender
{
mySegControl.selectedSegmentIndex = -1;
}
// called for UIControlEventValueChanged
- (void)segmentAction:(UISegmentedControl *)sender
{
NSInteger index = sender.selectedSegmentIndex;
NSLog(@"unitsSegmentAction %d",(int)index);
// process the segment
}
KVO를 사용하여 iOS8에서 이미 선택한 세그먼트를 반전하고 있습니다.
#import "QCSegmentedControl.h"
static void *QCSegmentedControlContext = &QCSegmentedControlContext;
@implementation QCSegmentedControl
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self registerKVO];
}
return self;
}
- (void)dealloc {
[self removeObserver:self forKeyPath:@"selectedSegmentIndex"];
}
#pragma mark -
- (void)registerKVO {
[self addObserver:self
forKeyPath:@"selectedSegmentIndex"
options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
context:QCSegmentedControlContext];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if (context == QCSegmentedControlContext) {
NSNumber *new = change[NSKeyValueChangeNewKey];
NSNumber *old = change[NSKeyValueChangeOldKey];
if (new.integerValue == old.integerValue) {
self.selectedSegmentIndex = UISegmentedControlNoSegment;
}
}
}
@end
선택한 답변의 솔루션은 현재 iOS v8.x에서 저에게 적합하지 않았습니다. 그러나 @Andy는 솔루션을 제공하고 완료합니다.
하위 클래스에서 UISegmentedControl
, 및 덮어 쓰기 touchesEnded
메서드를 하위 클래스에서 :
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self sendActionsForControlEvents:UIControlEventAllTouchEvents];
[super touchesEnded:touches withEvent:event];
}
UISegmentedControl을 사용하려는 클래스에서 iVar currentSelectedSegIndex를 만듭니다. UIControlEventValueChanged 작업 메서드 옆에 UIControlEventAllTouchEvents를 추가합니다.
NSInteger currentSelectedSegIndex;
[aSegmentedController addTarget:self action:@selector(aSegmentedControllerSelection:) forControlEvents:UIControlEventValueChanged];
[aSegmentedController addTarget:self action:@selector(aSegmentedControllerAllTouchEvent:) forControlEvents:UIControlEventAllTouchEvents];
두 가지 작업 방법을 구현합니다.
-(void)aSegmentedControllerAllTouchEvent:(MyUISegmentedControl *)seg
{
seg.selectedSegmentIndex = UISegmentedControlNoSegment;
}
-(void)aSegmentedControllerSelection:(MyUISegmentedControl *)seg
{
if (currentSelectedSegIndex == seg.selectedSegmentIndex)
{
seg.selectedSegmentIndex = UISegmentedControlNoSegment;
currentSelectedSegIndex = NSIntegerMax;
NSLog(@"%s Deselected.", __PRETTY_FUNCTION__);
// do your stuff if deselected
return;
}
NSLog(@"%s Selected index:%u", __PRETTY_FUNCTION__, seg.selectedSegmentIndex);
currentSelectedSegIndex = seg.selectedSegmentIndex;
//do your stuff if selected index
}
참고URL : https://stackoverflow.com/questions/1620972/uisegmentedcontrol-register-taps-on-selected-segment
'IT TIP' 카테고리의 다른 글
CSS를 사용하여 앤티 앨리어싱 강제 : 이것이 신화입니까? (0) | 2020.11.29 |
---|---|
삼각파를 생성하는 단선 함수가 있습니까? (0) | 2020.11.29 |
소프트 키보드에서 "완료"키 누름을 포착하는 방법 (0) | 2020.11.29 |
폴더 선택 대화 상자 WPF (0) | 2020.11.29 |
어셈블리 코드를 얻기 위해 Linux에서 바이너리 실행 파일을 분해하는 방법은 무엇입니까? (0) | 2020.11.29 |