터치 후 선택된 UIButton 유지


90

사용자가 버튼을 클릭 한 후 네트워크 작업을 수행하는 동안 해당 버튼을 계속 누르고 싶습니다. 네트워크 작업이 완료되면 버튼을 기본 상태로 되돌리고 싶습니다.

나는 [UIButton setSelected:YES]버튼을 누른 직후에 전화를 시도했지만 ( [UIButton setSelected:NO]내 네트워크 작업이 완료된 후에 해당하는 전화와 함께 ) 아무것도하지 않는 것 같습니다. 내가 전화해도 똑같아 setHighlighted:.

네트워크 작업이 진행되는 동안 선택된 상태를 나타 내기 위해 배경 이미지를 교체해 볼 수 있다고 생각하지만 해킹처럼 보입니다. 더 좋은 제안이 있습니까?

내 코드는 다음과 같습니다.

- (IBAction)checkInButtonPushed
{
    self.checkInButton.enabled = NO;
    self.checkInButton.selected = YES;
    self.checkInButton.highlighted = YES;
    [self.checkInActivityIndicatorView startAnimating];
    [CheckInOperation startWithPlace:self.place delegate:self];
}

- (void)checkInCompletedWithNewFeedItem:(FeedItem*)newFeedItem wasNewPlace:(BOOL)newPlace possibleError:(NSError*)error;
{
    [self.checkInActivityIndicatorView stopAnimating];
    self.checkInButton.enabled = YES;
    self.checkInButton.selected = NO;
    self.checkInButton.highlighted = NO;
}

답변:


73

UIControlStates버튼 의 다른 이미지를 어떻게 설정하고 있습니까? UIControlStateHighlighted뿐만 아니라 배경 이미지를 설정하고 UIControlStateSelected있습니까?

UIImage *someImage = [UIImage imageNamed:@"SomeResource.png"];
[button setBackgroundImage:someImage forState:UIControlStateHighlighted];
[button setBackgroundImage:someImage forState:UIControlStateSelected];

내부를 터치하는 대신 버튼 터치 다운 이벤트에서 선택한 상태를 설정하는 경우 버튼은 실제로 강조 표시된 + 선택된 상태가되므로 설정하는 것이 좋습니다.

[button setBackgroundImage:someImage forState:(UIControlStateHighlighted|UIControlStateSelected)];

편집하다:

댓글에있는 내 발언을 요약하고 게시 한 코드를 해결하려면 현재있는 전체 UIControl상태에 대한 배경 이미지를 설정해야합니다 . 코드 스 니펫에 따르면이 제어 상태는 비활성화 됨 + 선택됨 + 네트워크 작동 기간 동안 강조 표시됩니다. 이것은 다음을 수행해야 함을 의미합니다.

[button setBackgroundImage:someImage forState:(UIControlStateDisabled|UIControlStateHighlighted|UIControlStateSelected)];

을 제거하면 highlighted = YES다음이 필요합니다.

[button setBackgroundImage:someImage forState:(UIControlStateDisabled|UIControlStateSelected)];

사진 가져와? 이해가 되세요?


실제로 나는 당신이 제안한 것을하고 있다고 믿습니다. 저는 Interface Builder를 통해하고 있습니다. 위의 질문에 사용중인 코드를 추가했습니다 ... 아마 문제에 대해 밝힐 수 있습니까? 내가 원하는 동작은 네트워크 작동 기간 동안 버튼이 선택된 상태로 유지되기를 원한다는 것입니다. 내가 본 것은 버튼을 터치하면 강조 표시되고 터치가 완료되면 강조 표시가 사라진다는 것입니다. 버튼은 선택되지 않습니다. 왜 이것이 작동하지 않는지 이해가되지 않아서 어리석은 일을하고있는 것 같습니다. IB 연결을 모두 확인했는데 괜찮습니다 ...
— Greg Maletic

Interface Builder에서 강조 표시된 + 선택된 상태에 대한 배경 이미지를 설정할 수 없다고 생각합니다. 강조 표시된 상태와 선택한 상태 만 별도로 설정할 수 있습니다. 버튼이 강조 표시된 상태와 선택된 상태가 모두 설정된 상태라면 강조 표시되거나 선택한 이미지가 아닌 일반 이미지가 기본값이라고 생각합니다. 코드에서 선택 및 강조 표시가 모두 예가되도록 버튼의 상태를 설정합니다. checkInButtonPushed가 "Touch Up Inside"또는 다른 것에 연결되어 있습니까?
— Bryan Henry

네, "Touch Up Inside"에 연결되어 있습니다. 그리고 '강조 표시'상태와 관련된 코드를 제거해도 여전히 작동하지 않습니다. '선택됨'상태는 표시되지 않습니다.
— Greg Maletic

또한 버튼을 비활성화하는 이유는 무엇입니까? 이는 실제로 버튼 상태가 비활성화 됨 + 강조 표시됨 + 선택됨을 의미합니다. YES로 강조 표시된 라인 설정을 제거한 경우 비활성화 + 선택한 것이므로 (UIControlStateDisabled | UIControlStateSelected) 상태에 대한 이미지를 설정해야합니다.
— Bryan Henry

좋아요, 그게 문제였습니다. 비활성화 기능을 꺼냈을 때 예상대로 작동했습니다. 감사! (귀하의 질문에 답하기 위해, 네트워크 작동이 진행되는 동안 아무도 버튼을 다시 누르는 것을 원하지 않기 때문에 버튼을 비활성화합니다.)
— Greg Maletic

30

더 쉬운 방법이 있습니다. 를 수행하려면 지연 시간이 0 인 "performSelector"를 사용하십시오 [button setHighlighted:YES]. 현재 런 루프가 종료 된 후 다시 강조 표시됩니다.

- (IBAction)buttonSelected:(UIButton*)sender {
    NSLog(@"selected %@",sender.titleLabel.text);
    [self performSelector:@selector(doHighlight:) withObject:sender afterDelay:0];
}

- (void)doHighlight:(UIButton*)b {
    [b setHighlighted:YES];
}

28

"전원을 켜면 모든 것이 좋아집니다."

    button.selected = !button.selected;

인터페이스 빌더의 버튼에 콘센트를 연결 한 후 완벽하게 작동합니다.

setBackgroundImage : forState :가 필요하지 않습니다. 빌더는 배경 (필요한 경우 크기가 조정 됨) 또는 전경 (크기 조정이 아님) 이미지를 지정할 수 있습니다.


27

이를 위해 NSOperationQueue를 사용해보십시오. 다음과 같이 코드를 시도하십시오.

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    theButton.highlighted = YES;
}];

도움이 되었기를 바랍니다.


이것은 훌륭한 솔루션입니다. Roberto & Parth. 그러나 한 가지 작은 세부 사항은 사용자가 버튼에 손가락을 대면 가끔 "깜박임"이 표시된다는 것입니다. 깜박임을 방지 할 수있는 방법이 있습니까?
— Scott Lieberman 2013 년

8

블록을 사용하면 완전히 별도의 메서드를 만들 필요가 없습니다.

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0), dispatch_get_main_queue(), ^{
    theButton.highlighted = YES;
});

최신 정보

명확하게하기 위해 여전히 조합 상태에 대한 배경 (또는 일반 이미지)을 설정해야하며, sbrocket이 수락 된 답변에서 말하는 것과 같은 일반 이미지도 설정해야합니다. 어느 시점에서 버튼이 선택되고 강조 표시되며 다음과 같은 작업을 수행하지 않으면 해당 이미지가 표시되지 않습니다.

[button setBackgroundImage:someImage forState (UIControlStateHighlighted|UIControlStateSelected)];

그렇지 않으면 버튼이 간략하게 선택됨 + 강조 표시된 상태에 대한 UIControlStateNormal 이미지로 돌아갈 수 있으며 플래시가 표시됩니다.


FYI dispatch_get_current_queue()는 "신뢰할 수없는"것으로 표시됩니다.
— Jacob Relkin 2012 년

1
어디에 언급되어 있습니까? 대안은 무엇입니까?
— 밥 Spryn

dispatch_after반대로 사용 하는 데 의미 가 dispatch_async있습니까?
— Ilya

네. dispatch_async더 나은 선택입니다.
— Bob Spryn 2015

4

신속하게 나는 다음과 같이하고 있습니다.

하위 클래스를 만들고 UIButton사용자 지정 속성을 구현했습니다.state

class ActiveButton: UIButton {

    private var _active = false
    var active:Bool {
        set{
            _active = newValue
            updateState()
        }
        get{
            return _active
        }
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.addTarget(self, action: #selector(ActiveButton.touchUpInside(_:)), forControlEvents: .TouchUpInside)
    }

    func touchUpInside(sender:UIButton) {
        active = !active
    }

    private func updateState() {
        NSOperationQueue.mainQueue().addOperationWithBlock {
            self.highlighted = self.active
        }
    }

}

나를 위해 완벽하게 작동합니다.


1

클릭 후 강조 표시를 유지하는 버튼을 원했던 비슷한 문제가 있습니다. 문제는 setHighlighted:YES내부 클릭 동작 을 사용하려고 하면 동작을 클릭 한 후 바로 재설정되며,- (IBAction)checkInButtonPushed

나는 이와 같은 NSTimer를 사용하여 이것을 해결했습니다.

NSTimer *timer;
timer = [NSTimer scheduledTimerWithTimeInterval: 0.01
                                         target: self
                                       selector: @selector(selectCurrentIndex)
                                       userInfo: nil
                                        repeats: NO];

setHighlighted:YES내 selectCurrentIndex방법 에서 호출하십시오 . 나는 일반 UIButtonTypeRoundedRect버튼을 사용 합니다.


0

다른 방법이 있습니다 ... 이미지를 사용하고 싶지 않고 버튼을 누른 효과를 원한다면 Button을 하위 클래스로 만들 수 있으며 여기에 내 코드가 있습니다.

.h 파일에서 :

@interface reservasButton : UIButton {

BOOL isPressed;
}
 @end

.m 파일에서 :

#import <QuartzCore/QuartzCore.h>


 @implementation reservasButton

 -(void)setupView {  //This is for Shadow

    self.layer.shadowColor = [UIColor blackColor].CGColor;
    self.layer.shadowOpacity = 0.5; 
    self.layer.shadowRadius = 1;    
    self.layer.shadowOffset = CGSizeMake(2.0f, 2.0f); //comment
    //   self.layer.borderWidth = 1;
    self.contentVerticalAlignment   = UIControlContentVerticalAlignmentCenter;
    self.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;

    // [self setBackgroundColor:[UIColor whiteColor]];

    //  self.opaque = YES;


}

-(id)initWithFrame:(CGRect)frame{
    if((self = [super initWithFrame:frame])){
        [self setupView];
    }

    return self;
}

-(id)initWithCoder:(NSCoder *)aDecoder{
    if((self = [super initWithCoder:aDecoder])){
        [self setupView];
    }

    return self;
}

//Here is the important code

 -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{


  if (isPressed == FALSE) {

      self.contentEdgeInsets = UIEdgeInsetsMake(1.0,1.0,-1.0,-1.0);
      self.layer.shadowOffset = CGSizeMake(1.0f, 1.0f);
      self.layer.shadowOpacity = 0.8;

      [super touchesBegan:touches withEvent:event];

      isPressed = TRUE;

     }
     else {

         self.contentEdgeInsets = UIEdgeInsetsMake(0.0,0.0,0.0,0.0);
         self.layer.shadowOffset = CGSizeMake(2.0f, 2.0f);
         self.layer.shadowOpacity = 0.5;

         [super touchesEnded:touches withEvent:event];

         isPressed = FALSE;

     }


 } `

0

다음은 위에 제시된 접근 방식을 사용하는 C # / MonoTouch (Xamarin.iOS) 구현입니다. 강조 표시된 이미지 상태를 이미 설정했다고 가정하고 동일한 이미지를 사용하도록 선택 및 선택됨 상태를 구성합니다.

var selected = button.BackgroundImageForState(UIControlState.Highlighted);
button.SetBackgroundImage(selected, UIControlState.Selected);
button.SetBackgroundImage(selected, UIControlState.Selected | UIControlState.Highlighted);
button.TouchUpInside += delegate
{
    NSTimer.CreateScheduledTimer(TimeSpan.FromMilliseconds(0), delegate
    {
        button.Highlighted = true;
        NSTimer.CreateScheduledTimer(TimeSpan.FromMilliseconds(200), delegate
        {
            button.Highlighted = false;
        });
    });
};
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.