web-dev-qa-db-ja.com

タッチ後にUIButtonを選択したままにする

ユーザーがボタンをクリックした後、ネットワーク操作を実行している間、そのボタンが押されたままになるようにします。ネットワーク操作が完了したら、ボタンをデフォルトの状態に戻します。

ボタンを押した直後に-[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;
}
89
Greg Maletic

ボタン上の異なるUIControlStatesの画像をどのように設定していますか? UIControlStateHighlightedUIControlStateSelectedの背景画像を設定していますか?

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)];

その絵を手に入れる?

73
Bryan Henry

もっと簡単な方法があります。 「performSelector」を0遅延で使用して、[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];
}
30
Hlung

NSOperationQueueを使用して、これを達成してください。次のコードを試してください。

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

お役に立てれば。

27
roberto.buratti

「電源を入れるとすべてが良くなる」

    button.selected = !button.selected;

アウトレットをInterface Builderのボタンに接続した後、完全に機能します。

SetBackgroundImage:forState:を使用する必要はありません。ビルダーでは、背景(必要に応じてサイズ変更されます)または前景(サイズ変更しない)画像を指定できます。

27

ブロックを使用して、個別のメソッド全体を作成する必要がないようにします。

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

更新

明確にするために、受け入れられた回答でsbrocketが言うような通常の状態と同様に、組み合わせ状態の背景(または通常の画像)を設定する必要があります。ある時点で、ボタンが選択されて強調表示され、次のような操作を行わない限り、その画像は表示されなくなります。

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

そうでない場合、ボタンは短い選択状態+ハイライト状態のUIControlStateNormalイメージにフォールバックでき、フラッシュが表示されます。

8
Bob Spryn

In Swift私は次のようにやっています。

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
        }
    }

}

私にぴったりです。

2
Eike

クリック後もハイライトを維持するためのボタンが必要になるという同様の問題がありました。問題は、クリックアクションの内部で_setHighlighted:YES_を使用しようとすると、アクション[- (IBAction)checkInButtonPushed

このようなNSTimerを使用してこれを解決しました

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

selectCurrentIndexメソッドから_setHighlighted:YES_を呼び出します。通常のUIButtonTypeRoundedRectボタンを使用します。

1
fredrik

別の方法があります...画像を使用したくない場合、押されたボタンの効果が必要な場合は、ボタンをサブクラス化できます。ここに私のコードがあります:

.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
Pach

上記のアプローチを使用したC#/ MonoTouch(Xamarin.iOS)の実装を次に示します。 Highlighted image状態が既に設定されていることを前提とし、選択およびselected | highlighted状態が同じ画像を使用するように設定します。

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;
        });
    });
};
0
t9mike