      Animatable.
      */
     public func set(state: State.Settle) {
-        switch state {
-        case .expanded:
-            currentOffset = minOffset
-        case .anchored:
-            guard let anchorOffset = anchorOffset else { return }
-            currentOffset = anchorOffset
-        case .collapsed:
-            currentOffset = maxOffset
-        }
+        guard let newOffset = offset(forState: state) else { return }
+        currentOffset = newOffset
     }
     
     /// Returns the current state of `SlideOutable` view.
-    public private(set) var state: State {
+    public var state: State {
         switch currentOffset {
         case minOffset:
             return .settled(.expanded)

    var minOffset: CGFloat { return isScrollStretchable ? topPadding : max(topPadding, bounds.height - (header?.bounds.height ?? 0) - scroll.contentSize.height) }
    var maxOffset: CGFloat { return max(minOffset, bounds.height - minContentHeight) }
    var anchorOffset: CGFloat? { return anchorFraction.flatMap { bounds.height * (1 - $0) } }
    
    // MARK: - Scroll content size KVO
    

            return .settled(.collapsed)
        default:
            return .dragging(offset: currentOffset)
        }
    }
    
    func offset(forState state: State.Settle) -> CGFloat? {
        switch state {
        case .expanded:
            return minOffset
        case .anchored:
            return anchorOffset
        case .collapsed:
            return maxOffset
        }
    }
    
