         }
     }
     
-    private func _animateContinuousIndicator(_ show: Bool, at point: CGPoint) {
+    private func _animateScalingContinuousIndicator(at point: CGPoint) {
+        _autoFocusIndicator.isHidden = true
+        _autoExposeIndicator.isHidden = true
+        _untwinkle(content: _continuousIndicator)
+        _animateContinuousIndicator(true, at: point, checkingIsHidden: false)
+    }
+    
+    private func _animateContinuousIndicator(_ show: Bool, at point: CGPoint, checkingIsHidden: Bool = true, twinkle twinkleContent: Bool = true) {
         if show {
-            guard _continuousIndicator.isHidden else { return }
+            if checkingIsHidden {
+                guard _continuousIndicator.isHidden else { return }
+            }
             
             _continuousBeginning = Date()
+            _autoFocusIndicator.isHidden = true
+            _autoExposeIndicator.isHidden = true
             _continuousIndicator.isHidden = false
             _continuousIndicator.center = point
             _continuousIndicator.alpha = 0.0
             
-            let scale: CGFloat = 1.2
+            let scale: CGFloat = 1.5
             _continuousIndicator.transform = CGAffineTransform(scaleX: scale, y: scale)
+            
+            NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(__animateHideContinuousIndicator), object: nil)
             UIView.animate(withDuration: 0.1, animations: { [unowned self] in
                 self._continuousIndicator.alpha = 1.0
             }, completion: { (finished) in
                 if finished {
-                    UIView.animate(withDuration: 0.25, animations: { [unowned self] in
+                    UIView.animate(withDuration: 0.2, animations: { [unowned self] in
                         self._continuousIndicator.transform = .identity
                     }, completion: { [unowned self] (finished) in
-                        if finished {
+                        if twinkleContent && finished {
                             self._twinkle(content: self._continuousIndicator)
                         }
                     })
                 }
             })
         } else {
-            guard !_continuousIndicator.isHidden else { return }
-            
-            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1 + max(0.0, _graceTime - Date().timeIntervalSince(_continuousBeginning)), execute: { [unowned self] in
-                self._untwinkle(content: self._continuousIndicator)
-                UIView.animate(withDuration: 0.25, delay: 0.4, options: [], animations: { [unowned self] in
-                    self._continuousIndicator.alpha = 0.0
-                }, completion: { [unowned self] finished in
-                    if finished {
-                        self._continuousIndicator.isHidden = true
-                    }
-                })
-            })
-        }
-    }
-    
-    private func _animateAutoIndicators(_ show: Bool, at point: CGPoint) {
+            let delay = max(0.0, _graceTime - Date().timeIntervalSince(_continuousBeginning))
+            // print("delay: \(delay), grace: \(_graceTime) offset: \(Date().timeIntervalSince(_continuousBeginning))")
+            self.perform(#selector(__animateHideContinuousIndicator), with: nil, afterDelay: delay, inModes: [RunLoopMode.commonModes])
+        }
+    }
+    
+    @objc
+    private func __animateHideContinuousIndicator() {
+        guard !_continuousIndicator.isHidden else { return }
+        
+        self._untwinkle(content: self._continuousIndicator)
+        UIView.animate(withDuration: 0.25, delay: 0.4, options: [], animations: { [unowned self] in
+            self._continuousIndicator.alpha = 0.0
+        }, completion: { [unowned self] finished in
+            if finished {
+                self._continuousIndicator.isHidden = true
+            }
+        })
+    }
+    
+    private func _animateAutoIndicators(_ show: Bool, at point: CGPoint, scale: CGFloat = 1.5, showsCompletion: (() -> Void)? = nil) {
         if show {
             _autoBeginning = Date()
+            _continuousIndicator.isHidden = true
             _autoFocusIndicator.isHidden = false
             _autoExposeIndicator.isHidden = false
             _autoFocusIndicator.alpha = 0.0
             _autoExposeIndicator.alpha = 0.0
             _autoFocusIndicator.center = point
             
-            let scale: CGFloat = 1.5
             _autoFocusIndicator.transform = CGAffineTransform(scaleX: scale, y: scale)
             switch point.x {
             case 0...(bounds.width - _autoFocusIndicator.bounds.width * 0.5 - (_paddingOfFocusAndExpose + _autoExposeIndicator.bounds.width)):

                _autoExposeIndicator.transform = CGAffineTransform(scaleX: scale, y: scale).translatedBy(x: -_autoFocusIndicator.bounds.width * 0.5 * (scale - 1.0), y: 0.0)
            }
            
            
            UIView.animate(withDuration: 0.1, animations: { [unowned self] in
                self._autoFocusIndicator.alpha = 1.0
                self._autoExposeIndicator.alpha = 1.0

            if device.focusMode != .continuousAutoFocus {
                let point = CGPoint(x: 0.5, y: 0.5)
                _focus(using: .continuousAutoFocus, exposure: .continuousAutoExposure, at: point)
            }
        }
    }
    
    @objc
    fileprivate func _handleTapToConfigureDevice(_ sender: UITapGestureRecognizer) {
        guard sender.state == .ended else { return }
        
        let location = sender.location(in: self)
        let point = previewLayer.captureDevicePointOfInterest(for: location)
        
        humanReadingInfos = []
        
        _focus(using: .autoFocus, exposure: .autoExpose, at: point)
        _animateIndicators(show: true, mode: .autoFocus, at: location)
    }
    
    @objc
    fileprivate func _handleLongPressToConfigureDevice(_ sender: UILongPressGestureRecognizer) {
        switch sender.state {
        case .possible: fallthrough
        case .began:
            let location = sender.location(in: self)
            let pointOfInterest = previewLayer.captureDevicePointOfInterest(for: location)
            // _lockFocusAndExpose(at: previewLayer.captureDevicePointOfInterest(for: location))
            _focus(using: .autoFocus, exposure: .autoExpose, at: pointOfInterest, monitorSubjectAreaChange: false)
            _animateScalingContinuousIndicator(at: location)
            humanReadingInfos = ["自动曝光/自动对焦锁定"]
        case .changed: break
            // print("Long press gesture is changing.")
        case .failed: fallthrough
        case .cancelled: fallthrough
        default:
            if let device = videoDevice {
                _animateAutoIndicators(true, at: _continuousIndicator.center, scale: _continuousIndicator.bounds.width / _autoFocusIndicator.bounds.width) { [unowned self] in
                    if device.focusMode == .locked {
                        self._pinAutoIndicators()
                    }
                }
            }
        }
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if context == &_deviceIsAdjustingFocusObserveContext && keyPath == "adjustingFocus" {
            if let adjustingFocus = change?[.newKey] as? Bool, let device = videoDevice {
                print("is adjusting focus: " + adjustingFocus.description)
                let location = previewLayer.pointForCaptureDevicePoint(ofInterest: device.focusPointOfInterest)
                if device.focusMode == .autoFocus {
                    if _focusLongPressGesture.state == .changed {
                        _animateScalingContinuousIndicator(at: location)
                    }
                } else {
                    _animateIndicators(show: adjustingFocus, mode: device.focusMode, at: location)
                }
            }
        } else if context == &_deviceFocusModeObserveContext && keyPath == "focusMode" {
            if let focusMode = change?[.newKey] as? Int, let device = videoDevice {
                print("new focus mode: " + focusMode.description)
                if AVCaptureFocusMode(rawValue: focusMode) == .locked && !device.isAdjustingFocus && _focusLongPressGesture.state != .changed {
                    _animateIndicators(show: true, mode: .locked, at: .zero)
                }
            }
        } else if context == &_deviceFlashActiveObserveContext && keyPath == "flashActive" {
            if let isFlashActive = change?[.newKey] as? Bool {
                print("new flash mode: " + isFlashActive.description)
                if isFlashActive {
                    humanReadingInfos = [[#imageLiteral(resourceName: "flash_auto")], humanReadingInfos].joined().reversed()
                }
            }
        } else {
