     
     // MARK: - Scroll content size KVO
     
-    private var scrollContentSizeContext = 0
+    private var scrollContentContext = 0
     
     public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
-        guard context == &scrollContentSizeContext else {
+        guard context == &scrollContentContext else {
             super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
             return
         }
-        guard !isScrollStretchable else { return }
-        update()
+        guard let keyPath = keyPath else { return }
+        switch keyPath {
+        case #keyPath(UIScrollView.contentOffset):
+            guard lastScrollOffset != scroll.contentOffset.y else { return }
+            scrollViewDidScroll(scroll)
+        case #keyPath(UIScrollView.contentSize):
+            guard !isScrollStretchable else { return }
+            update()
+        default:
+            break
+        }
     }
     
     // MARK: - State

        
        scroll.panGestureRecognizer.addTarget(self, action: #selector(SlideOutable.didPanScroll(_:)))
        
        scroll.addObserver(self, forKeyPath: #keyPath(UIScrollView.contentSize), options: .new, context: &scrollContentSizeContext)
        
        defer {
            updateScrollSize()

    }
    
    deinit {
        scroll.removeObserver(self, forKeyPath: #keyPath(UIScrollView.contentSize), context: &scrollContentContext)
        scroll.removeObserver(self, forKeyPath: #keyPath(UIScrollView.contentOffset), context: &scrollContentContext)
    }
    
    // MARK: - Properties
