Bir dokunuştan sonra bir UIB düğmesinin seçili tutulması


90

Kullanıcım bir düğmeyi tıkladıktan sonra, bir ağ işlemi gerçekleştirdiğim süre boyunca bu düğmenin basılı kalmasını istiyorum. Ağ işlemi tamamlandığında, düğmenin varsayılan durumuna dönmesini istiyorum.

[UIButton setSelected:YES]Aramayı denedim - düğmeye basıldıktan hemen sonra ( [UIButton setSelected:NO]ağ işlemim bittikten sonra - karşılık gelen bir çağrı ile ) ama hiçbir şey yapmıyor gibi görünüyor. Ararsam da aynı şey setHighlighted:.

Sanırım ağ operasyonu süresince seçilen bir durumu belirtmek için arka plan görüntüsünü değiştirmeyi deneyebilirim, ancak bu bir hack gibi görünüyor. Daha iyi bir öneriniz var mı?

Kodum şöyle görünüyor:

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

Yanıtlar:


73

Düğmedeki farklı için görüntüleri nasıl ayarlıyorsunuz UIControlStates? Eğer bir arka plan resmi ayarlarken UIControlStateHighlightedyanı sıra UIControlStateSelected?

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

İçeride dokunmak yerine düğme dokunma olayında seçili durumu ayarlıyorsanız, düğmeniz aslında vurgulanmış + seçili durumda olacaktır, bu nedenle bunu da ayarlamak isteyeceksiniz.

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

Düzenle:

Yorumlardaki yorumlarımı özetlemek ve gönderdiğiniz kodu ele almak için ... içinde bulunduğunuz tam UIControlduruma göre arka plan resimlerinizi ayarlamanız gerekir . Kod pasajınıza göre, bu kontrol durumu devre dışı bırakılır + seçili + ağ çalışması süresince vurgulanır. Bu, bunu yapmanız gerektiği anlamına gelir:

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

Kaldırırsanız, highlighted = YESşuna ihtiyacınız olacaktır:

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

Resmi al?


Aslında, önerdiğiniz şeyi yaptığıma inanıyorum; Bunu sadece Interface Builder ile yapıyorum. Kullandığım kodu yukarıdaki soruma ekledim ... belki bu soruna biraz ışık tutabilir mi? İstediğim davranış, düğmenin ağ işlemim boyunca seçili kalmasını istememdir. Gördüğüm şey, düğmeye dokunulduğunda vurgulanıyor, ardından dokunma tamamlandığında vurgu kayboluyor. Düğme asla seçilmez. Bunun neden işe yaramadığı bana mantıklı gelmiyor, bu yüzden aptalca bir şey yaptığımı hissediyorum. Tüm IB bağlantılarımı kontrol ettim ve iyi durumda ...
Greg Maletic

Arayüz Oluşturucu'da vurgulanan + seçili durum için bir arka plan görüntüsü ayarlayabileceğinizi sanmıyorum, yalnızca vurgulanan ve seçilen durumlar ayrı ayrı. Düğmeniz hem vurgulanan hem de seçilen şekilde ayarlanmış bir durumdaysa, varsayılan olarak vurgulanan veya seçilen görüntülerin değil, normal görüntünüzün varsayılacağına inanıyorum. Kodunuzdan, düğmenin durumunu, hem seçilen hem de vurgulananlar EVET olacak şekilde ayarlıyorsunuz. CheckInButtonPushed "Touch Up Inside" ya da başka bir şeye bağlı mı?
Bryan Henry

Evet, "İçeride Rötuş Yap" a bağlı. Ve 'vurgulanmış' durumla ilgili kodu kaldırırsam, yine de çalışmıyor. 'Seçilmiş' durum asla gösterilmez.
Greg Maletic

Ayrıca, düğmeyi neden devre dışı bırakıyorsunuz? Bu aslında düğme durumunun devre dışı bırakıldığı + vurgulanmış + seçildiği anlamına gelir. EVET olarak vurgulanan satır ayarını kaldırdıysanız, devre dışı bıraktınız + seçtiniz, bu nedenle (UIControlStateDisabled | UIControlStateSelected) durumu için bir görüntü ayarlamanız gerekir.
Bryan Henry

Tamam, sorun buydu. Devre dışı bırakma işlevini çıkardığımda beklendiği gibi çalıştı. Teşekkürler! (Sorunuzu yanıtlamak için, düğmeyi devre dışı bırakıyorum çünkü ağ işlemi devam ederken kimsenin düğmeye tekrar basmasını istemiyorum.)
Greg Maletic,

30

Daha kolay bir yolum var. Gerçekleştirmek için 0 gecikmeli "performSelector" kullanın [button setHighlighted:YES]. Bu, geçerli çalışma döngüsü bittikten sonra yeniden vurgulama gerçekleştirecektir.

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

"Gücü açtığınızda her şey daha iyi hale gelir"

    button.selected = !button.selected;

Arayüz Oluşturucu'daki düğmeye prizi bağladıktan sonra mükemmel çalışıyor.

BackgroundImage: forState: ayarlamanıza gerek yoktur, oluşturucu arka plan (gerekirse yeniden boyutlandırılır) ve / ve ön plan (yeniden boyutlandırma değil) görüntüleri belirlemenize izin verir.


27

Bunu başarmak için NSOperationQueue kullanmayı deneyin. Kodu aşağıdaki gibi deneyin:

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

Bu yardımcı olur umarım.


Bu harika bir çözüm, Roberto & Parth. Ancak küçük bir ayrıntı, kullanıcı parmağını düğme üzerinde tuttuğunda ara sıra bir "titreme" görmenizdir. Titremeyi önlemenin bir yolu var mı?
Scott Lieberman

8

Tamamen ayrı bir yöntem oluşturmanıza gerek kalmaması için bir blok kullanın:

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

Güncelleme

Açık olmak gerekirse, kombinasyon durumlarının yanı sıra sbrocket gibi normal olanların kabul edilen yanıtta söylediği arka planı (veya normal görüntüyü) ayarlamanız gerekir. Bir noktada düğmeniz hem seçilecek hem de vurgulanacak ve şunun gibi bir şey yapmadığınız sürece bunun için bir resminiz olmayacak:

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

Aksi takdirde, düğmeniz kısa seçili + vurgulanmış durum için UIControlStateNormal görüntüsüne geri dönebilir ve bir flaş görürsünüz.


Bilginize dispatch_get_current_queue()"güvenilmez" olarak belirtiliyor.
Jacob Relkin

1
Bu nerede belirtiliyor? Alternatif nedir?
Bob Spryn

Kullanmada orada önemi var mı dispatch_afteraksine dispatch_async?
Ilya

Evet. dispatch_asyncdaha iyi bir seçimdir.
Bob Spryn

4

Hızla aşağıdaki gibi yapıyorum.

UIButtonÖzel bir özellik için bir Alt Sınıf oluşturdum ve uyguladımstate

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

}

Benim için mükemmel çalışıyor.


1

Bir düğmenin tıkladıktan sonra vurgulanmasını istediğimde benzer bir sorun yaşadım. Sorun şu ki setHighlighted:YES, tıklama eyleminizin içinde kullanmaya çalışırsanız, eylemi tıkladıktan hemen sonra sıfırlanacaktır,- (IBAction)checkInButtonPushed

Bunu, bunun gibi bir NSTimer kullanarak çözdüm

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

ve sonra setHighlighted:YESbenim selectCurrentIndexyöntemimden arayın . Normal UIButtonTypeRoundedRectdüğmeler kullanıyorum.


0

Başka bir yolum var ... görüntüleri kullanmak istemiyorsan ve basılan bir düğmenin etkisini istiyorsanız, Düğmeyi alt sınıflara ayırabilirsiniz ve işte kodum:

.h Dosyasında:

@interface reservasButton : UIButton {

BOOL isPressed;
}
 @end

.M Dosyasında:

#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

Yukarıda sunulan yaklaşımları kullanan bir C # / MonoTouch (Xamarin.iOS) uygulaması aşağıda verilmiştir. Vurgulanan görüntü durumunu zaten ayarladığınızı varsayar ve seçilen ve seçilen | vurgulanan durumları aynı görüntüyü kullanacak şekilde yapılandırır.

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;
        });
    });
};
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.