How to set screen brightness with fade animation?

Is it possible to animate the change in screen brightness on iOS 5.1+? I use [UIScreen mainScreen] setBrightness:(float)], but I think the sudden change is ugly.

+6
source share
6 answers

I don’t know if this is β€œanimated” in any other way, but you can do it yourself. For example, the following sample code was connected to the Full Bright and Half Bright buttons in the user interface. It uses performSelector ... afterDelay to change the brightness by 1% every 10 ms until the target brightness is reached. You would choose a suitable rate of change based on some experiments. In fact, the refresh rate is, in my opinion, 60 Hz, so it may not make sense to make changes with an interval of less than 1/60 of a second (good math was chosen for my example). Although you might want to do this on a thread other than the UI, it does not block the user interface.

- (IBAction)fullBright:(id)sender {
    CGFloat brightness = [UIScreen mainScreen].brightness;
    if (brightness < 1) {
        [UIScreen mainScreen].brightness += 0.01;
        [self performSelector:@selector(fullBright:) withObject:nil afterDelay:.01];
    }
}

- (IBAction)halfBright:(id)sender {
    CGFloat brightness = [UIScreen mainScreen].brightness;
    if (brightness > 0.5) {
        [UIScreen mainScreen].brightness -= 0.01;
        [self performSelector:@selector(halfBright:) withObject:nil afterDelay:.01];
    }
}
+6
source

. :

extension UIScreen {

    func setBrightness(_ value: CGFloat, animated: Bool) {
        if animated {
            _brightnessQueue.cancelAllOperations()
            let step: CGFloat = 0.04 * ((value > brightness) ? 1 : -1)
            _brightnessQueue.add(operations: stride(from: brightness, through: value, by: step).map({ [weak self] value -> Operation in
                let blockOperation = BlockOperation()
                unowned let _unownedOperation = blockOperation
                blockOperation.addExecutionBlock({
                    if !_unownedOperation.isCancelled {
                        Thread.sleep(forTimeInterval: 1 / 60.0)
                        self?.brightness = value
                    }
                })
                return blockOperation
            }))
        } else {
            brightness = value
        }
    }

}

private let _brightnessQueue: OperationQueue = {
    let queue = OperationQueue()
    queue.maxConcurrentOperationCount = 1
    return queue
}()
+10

:

  extension UIScreen {

    private static let step: CGFloat = 0.1

    static func animateBrightness(to value: CGFloat) {
        guard fabs(UIScreen.main.brightness - value) > step else { return }

        let delta = UIScreen.main.brightness > value ? -step : step

        DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
            UIScreen.main.brightness += delta
            animateBrightness(to: value)
        }
    }
}
+1

Based on the remarks of Charlie Price, here is a description of the method of "revitalizing" the change in screen brightness for any desired value.

- (void)graduallyAdjustBrightnessToValue:(CGFloat)endValue
{
    CGFloat startValue = [[UIScreen mainScreen] brightness];

    CGFloat fadeInterval = 0.01;
    double delayInSeconds = 0.01;
    if (endValue < startValue)
        fadeInterval = -fadeInterval;

    CGFloat brightness = startValue;
    while (fabsf(brightness-endValue)>0) {

        brightness += fadeInterval;

        if (fabsf(brightness-endValue) < fabsf(fadeInterval))
            brightness = endValue;

        dispatch_time_t dispatchTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
        dispatch_after(dispatchTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [[UIScreen mainScreen] setBrightness:brightness];
        });
    }
}
0
source

Or you can use NSTimer instead of loops and execute a Selector .

finalValue is the value you want to achieve.

The timer works 30 times with a duration of 0.02 seconds for each (you can choose something else, but smoothly) and change the brightness value.

weak var timer: NSTimer?
var count = 1
let maxCount = 30
let interval = 0.02


timer = NSTimer
            .scheduledTimerWithTimeInterval(interval,
                                            target: self,
                                            selector: #selector(changeBrightness),
                                            userInfo: nil,
                                            repeats: true)
func changeBrightness()
{
    guard count < maxCount else { return }

    let currentValue = UIScreen.mainScreen().brightness 
    let restCount = maxCount - count
    let diff = (finalValue - currentValue) / CGFloat(restCount)
    let newValue = currentValue + diff
    UIScreen.mainScreen().brightness = newValue

    count += 1
}
0
source

Swift 5

import Foundation

extension UIScreen {

    public func setBrightness(to value: CGFloat, duration: TimeInterval = 0.3, ticksPerSecond: Double = 120) {
        let startingBrightness = UIScreen.main.brightness
        let delta = value - startingBrightness
        let totalTicks = Int(ticksPerSecond * duration)
        let changePerTick = delta / CGFloat(totalTicks)
        let delayBetweenTicks = 1 / ticksPerSecond

        let time = DispatchTime.now()

        for i in 1...totalTicks {
            DispatchQueue.main.asyncAfter(deadline: time + delayBetweenTicks * Double(i)) {
                UIScreen.main.brightness = max(min(startingBrightness + (changePerTick * CGFloat(i)),1),0)
            }
        }

    }
}
0
source

All Articles