È possibile animare la modifica della luminosità dello schermo su iOS 5.1+? Sto usando [UIScreen mainScreen] setBrightness:(float)]
ma penso che il brusco cambiamento sia brutto.Come impostare la luminosità dello schermo con le animazioni di dissolvenza?
risposta
Non so se questo è "animabile" in qualche altro modo, ma potresti farlo tu stesso. Ad esempio il seguente codice di esempio è stato collegato ai pulsanti "Full Bright" e "Half Bright" nell'interfaccia utente. Usa performSelector ... afterDelay per modificare la luminosità dell'1% ogni 10ms fino a raggiungere la luminosità target. Sceglieresti un tasso di cambio appropriato in base ad alcuni esperimenti. In realtà, la frequenza di aggiornamento è, credo, 60 Hz, quindi probabilmente non c'è motivo di fare un cambiamento in un intervallo inferiore a 1/60 di secondo (la mia frequenza di esempio è stata scelta per avere una buona matematica). Sebbene si desideri eseguire questa operazione su un thread non dell'interfaccia utente, non blocca l'interfaccia utente.
- (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];
}
}
Basato sul grande risposta di Charlie Price, ecco un metodo per "animare" un cambiamento di luminosità dello schermo a qualsiasi valore desiderato.
- (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];
});
}
}
Ho riscontrato problemi con la risposta accettata quando si tenta di animare su un altro valore con un'animazione precedente in corso. Questa soluzione annulla un'animazione in corso e anima per il nuovo valore:
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
}()
oppure è possibile utilizzare NSTimer invece di cicli while e performSelector.
finalValue - è il valore che si desidera raggiungere.
Il timer scatta 30 volte con una durata di 0,02 secondi per ciascuna (è possibile scegliere qualcosa di diverso ma uniformemente) e modifica il valore della luminosità.
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
}
Un'estensione 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)
}
}
}