8

是否可以在 iOS 5.1+ 上为屏幕亮度变化设置动画?我正在使用[UIScreen mainScreen] setBrightness:(float)],但我认为突然的变化是丑陋的。

4

7 回答 7

11

在尝试使用正在进行的前一个动画制作另一个值时,我遇到了接受答案的问题。此解决方案取消正在进行的动画并将动画设置为新值:

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
}()
于 2016-06-03T23:02:45.223 回答
11

斯威夫特 5

import UIKit

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)
            }
        }
        
    }
}
于 2019-05-15T16:20:44.157 回答
6

我不知道这是否以其他方式“动画化”,但你可以自己做。例如,以下示例代码连接到 UI 中的“全亮”和“半亮”按钮。它使用performSelector...afterDelay每 10ms 将亮度更改 1%,直到达到目标亮度。您将根据一些实验选择适当的更改率。实际上,我认为刷新率是 60 赫兹,因此以小于 1/60 秒的时间间隔进行更改可能没有意义(我选择的示例速率是为了得到很好的数学运算)。尽管您可能希望在非 UI 线程上执行此操作,但它不会阻塞 UI。

- (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];
    }
}
于 2013-04-05T19:20:41.187 回答
1

一个 Swift 扩展:

  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)
        }
    }
}
于 2018-03-06T18:47:37.873 回答
0

根据 Charlie Price 的出色回答,这是一种将屏幕亮度“动画化”为任何所需值的方法。

- (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];
        });
    }
}
于 2014-10-12T03:16:44.877 回答
0

或者您可以使用NSTimer代替 while 循环和 performSelector。

finalValue - 是您想要实现的价值。

计时器触发 30 次,每次持续时间为 0.02 秒(您可以选择不同但平滑的东西)并更改亮度值。

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
}
于 2016-06-15T15:59:44.950 回答
0

如果您需要更改特定 ViewController 的亮度,可以使用此助手

import Foundation
import UIKit

final class ScreenBrightness {

    private var timer: Timer?
    private var brightness: CGFloat?
    private var isBrighteningScreen = false
    private var isDarkeningScreen = false

    private init() { }

    static let shared = ScreenBrightnessHelper()

    //Увеличение яркости экрана до максимального уровня
    func brightenDisplay() {
        resetTimer()
        isBrighteningScreen = true
        if #available(iOS 10.0, *), timer == nil {
            brightness = UIScreen.main.brightness
            timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) { (timer) in
                UIScreen.main.brightness = UIScreen.main.brightness + 0.01
                if UIScreen.main.brightness > 0.99 || !self.isBrighteningScreen {
                    self.resetTimer()
                }
            }
        }
        timer?.fire()
    }

    //Затемнение экрана до предыдущего уровня
    func darkenDisplay() {
        resetTimer()
        isDarkeningScreen = true
        guard let brightness = brightness else {
            return
        }
        if #available(iOS 10.0, *), timer == nil {
            timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) { (timer) in
                UIScreen.main.brightness = UIScreen.main.brightness - 0.01

                if UIScreen.main.brightness <= brightness || !self.isDarkeningScreen {
                    self.resetTimer()
                    self.brightness = nil
                }
            }
            timer?.fire()
        }
    }

    private func resetTimer() {
        timer?.invalidate()
        timer = nil
        isBrighteningScreen = false
        isDarkeningScreen = false
    }
}

在 viewWillAppear 中调用 ScreenBrightness.shared.brightenDisplay() 如果你想改变它,调用方法 ScreenBrightness.shared.darkenDisplay() 将改变亮度

于 2020-11-17T11:00:05.937 回答