タッチ後も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)];

写真をゲット?


事実、私はあなたが提案したことをやっていると信じています。私は、インターフェイスビルダーを通じてそれを行っています。上記の質問に使用しているコードを追加しました...おそらく問題に光を当てるでしょうか?必要な動作は、ネットワーク操作中、ボタンを選択したままにしておくことです。私が見ているのは、ボタンがタッチされるとハイライトし、タッチが完了するとハイライトが消えることです。ボタンは選択されません。これがうまくいかない理由は私には意味がないので、私は愚かなことをしているように感じます。私はすべてのIB接続を確認しましたが、良好です
グレッグ・マレティック2009年

Interface Builderで強調表示+選択状態の背景画像を設定できるとは思いません。強調表示と選択状態だけを個別に設定できます。ボタンが強調表示と選択の両方が設定された状態にある場合、強調表示または選択された画像ではなく、通常の画像がデフォルトになると思います。コードから、ボタンの状態を設定して、選択と強調表示の両方がYESになるようにします。checkInButtonPushedは「Touch Up Inside」または他の何かに接続されていますか?
ブライアンヘンリー

はい、「Touch Up Inside」に接続されています。また、「強調表示された」状態に関連するコードを削除しても、機能しません。「選択された」状態は表示されません。
グレッグマレティック2009年

また、なぜボタンを無効にするのですか?つまり、ボタンの状態が無効+ハイライト+選択されているということです。ハイライトされた行設定を削除してYESにすると、無効化+選択されたので、(UIControlStateDisabled | UIControlStateSelected)状態の画像を設定する必要があります。
ブライアンヘンリー

それが問題でした。無効化機能を削除すると、期待どおりに機能しました。ありがとう!(ネットワーク操作が進行している間、私は再び、誰がそれをプッシュしたくないので、私はボタンを無効にしています、あなたの質問に答えるために。)
グレッグ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。ただし、細かい点の1つは、ユーザーがボタンを押したままにすると「ちらつき」が発生することがあります。ちらつきを防ぐ方法はありますか?
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
それはどこに述べられていますか?代わりは何ですか?
Bob Spryn 2012

とはdispatch_after対照的に使用することに意味はありdispatch_asyncますか?
2015

うん。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

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

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