터치 후 선택된 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:YESselectCurrentIndex방법 에서 호출하십시오 . 나는 일반 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.