2015-02-28 11 views
6

Bir kullanıcı belirli bir alanın üzerine geldiğinde, yeni görünümde çekmece benzeri bir animasyon göründüğü bir özelliği uygulamak istiyorum. Ayrıca, kullanıcı belirli bir alanı terk ettiğinde, çekmece animasyonla gitmelidir. Bu, Dock'un göründüğü ve animasyonla birlikte kaybolduğu OS X'deki ekranın alt kısmına geldiğinizde gördüğünüz şeydir. Ben animasyon ile özelliğini uygulamak eğer mouseExited: animasyon tamamlandığında önce belirli bir alan yeniden girdiğinizdeNSTrackingArea'nın faresi nasıl uygulanırEntered/Animasyon ile çıkıldı?

Ancak, düzgün çalışmıyor. İşte benim kod: Bu kodu

let trackingArea = NSTrackingArea(rect: CGRectMake(0, 0, 120, 300), options: NSTrackingAreaOptions.ActiveAlways | NSTrackingAreaOptions.MouseEnteredAndExited, owner: self, userInfo: nil) 
underView.addTrackingArea(trackingArea) // underView is the dummy view just to respond to the mouse tracking, since the drawerView's frame is changed during the animation; not sure if this is the clean way... 

override func mouseEntered(theEvent: NSEvent) { 
    let frameAfterVisible = CGRectMake(0, 0, 120, 300) 
    NSAnimationContext.runAnimationGroup({ 
     (context: NSAnimationContext!) in 
      context.duration = 0.6 
      self.drawerView.animator().frame = frameAfterVisible 
     }, completionHandler: {() -> Void in 
    }) 
} 

override func mouseExited(theEvent: NSEvent) { 
    let frameAfterInvisible = CGRectMake(-120, 0, 120, 300) 
    NSAnimationContext.runAnimationGroup({ 
     (context: NSAnimationContext!) in 
      context.duration = 0.6 
      self.drawerView.animator().frame = frameAfterInvisible 
     }, completionHandler: {() -> Void in 
    }) 
} 

// drawerView's frame upon launch is (-120, 0, 120, 300), since it is not visible at first 

, ben onun x pozisyonunu değiştirerek drawerView animasyon. Ancak, belirttiğim gibi, izleme alanına girdiğinizde ve izleme bölgesini terkettiğinizde, çekmece düzgün çalışıyor. Ancak, ayrılma animasyonu tamamen tamamlanmadan önce izleme alanına yeniden girerseniz durum böyle değildir.

Elbette animasyon süresini 0.1 gibi daha kısa olarak ayarlarsam bu nadiren olur. Ama manzarayı animasyonla taşımak istiyorum.

Ne yapmak istediğiniz görünüm kaybolan tamamlamadığı bile yine görünmesini drawerView başlangıç ​​yapmak olduğunu. Bunu yapmak için herhangi bir uygulama var mı?

+0

Animasyon devam ederken yeniden girdiğinizde 'mouseEntered() işlevi çağrılıyor mu? Yani, çağrılmadığı veya yeni çerçevenin ayarının etkili olmadığı sorun mu? Her iki işlevde de, animasyon grubundan önce, animasyon grubunun sonundaki ve tamamlama işleyicisinde bir miktar veri kaydı koyun. –

cevap

8

Kodunuza çok benzeyen bir çözümüm var. Farklı olan şey, NSTrackingArea'u çekmece görünümünü içeren görünümde değil, çekmece görünümünde kurduğumdur.

Bu açıkça, çekmecenin biraz “yapışması” gerektiği anlamına gelir. Benim durumumda, çekmece aşağıdayken görülebilen küçük bir görüntüdür, çünkü bir görüntü görüntüsü koyuyorum. Eğer istemiyorsan, çekmecenin görünen alanını boş ve yarı saydam bırakmanı öneririm. https://github.com/st3fan/StackOverflow-28777670-TrackingArea

de

private enum DrawerPosition { 
    case Up, Down 
} 

private let DrawerHeightWhenDown: CGFloat = 16 
private let DrawerAnimationDuration: NSTimeInterval = 0.75 

class ViewController: NSViewController { 

    @IBOutlet weak var drawerView: NSImageView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // Remove the auto-constraints for the image view otherwise we are not able to change its position 
     view.removeConstraints(view.constraints) 
     drawerView.frame = frameForDrawerAtPosition(.Down) 

     let trackingArea = NSTrackingArea(rect: drawerView.bounds, 
      options: NSTrackingAreaOptions.ActiveInKeyWindow|NSTrackingAreaOptions.MouseEnteredAndExited, 
       owner: self, userInfo: nil) 
     drawerView.addTrackingArea(trackingArea) 
    } 

    private func frameForDrawerAtPosition(position: DrawerPosition) -> NSRect { 
     var frame = drawerView.frame 
     switch position { 
     case .Up: 
      frame.origin.y = 0 
      break 
     case .Down: 
      frame.origin.y = (-frame.size.height) + DrawerHeightWhenDown 
      break 
     } 
     return frame 
    } 

    override func mouseEntered(event: NSEvent) { 
     NSAnimationContext.runAnimationGroup({ (context: NSAnimationContext!) in 
      context.duration = DrawerAnimationDuration 
      self.drawerView.animator().frame = self.frameForDrawerAtPosition(.Up) 
     }, completionHandler: nil) 
    } 

    override func mouseExited(theEvent: NSEvent) { 
     NSAnimationContext.runAnimationGroup({ (context: NSAnimationContext!) in 
      context.duration = DrawerAnimationDuration 
      self.drawerView.animator().frame = self.frameForDrawerAtPosition(.Down) 
     }, completionHandler: nil) 
    } 
} 

Tam projesi bu yararlı olduğunu bana bildirin:

İşte benim uygulamasıdır. Değişiklikler yapmaktan mutluluk duyuyorum.

+9

Dikkat edin, Swift 2.0'dan itibaren izleme alanı seçenekleri için başka bir sözdizimi takip etmeniz gerekiyor. trackingArea = NSTrackingArea izin (rect: self.bounds, seçenekler: [NSTrackingAreaOptions.MouseEnteredAndExited, NSTrackingAreaOptions.ActiveAlways], sahip: self, userInfo: nil) –

5

Swift 3. Başlangıç ​​Sen böyle yapmak gerekir:

let trackingArea = NSTrackingArea(rect: CGRectMake(0, 0, 120, 300), options: [NSTrackingAreaOptions.ActiveAlways ,NSTrackingAreaOptions.MouseEnteredAndExited], owner: self, userInfo: nil) 
view.addTrackingArea(trackingArea) 

Kredi yukarıda @marc!

İlgili konular