Как мгновенно перемещать CALayer (без анимации)

Я пытаюсь перетащить CALayer в приложение для iOS.

Как только я изменяю его свойство position, он пытается анимировать новое положение и мерцает повсюду:

 layer.position = CGPointMake(x, y)

Как я могу сразу CALayers переехать? Я не могу разобраться в Core Animation API.


person Mel    schedule 22.10.2008    source источник
comment
относительно этого чрезвычайно старого QA, критическая проблема сегодня заключается в следующем: stackoverflow.com/a/56980329/294884 < / а>   -  person Fattie    schedule 22.01.2020


Ответы (5)


Вы хотите завершить свой звонок следующим образом:

[CATransaction begin]; 
[CATransaction setValue: (id) kCFBooleanTrue forKey: kCATransactionDisableActions];
layer.position = CGPointMake(x, y);
[CATransaction commit];
person Ben Gottlieb    schedule 22.10.2008
comment
Это именно то. Я даже не подумал о CATransaction. Большое спасибо! - person Mel; 22.10.2008
comment
Ага, 6 с половиной лет спустя. Все еще полезно. : D - person Fogmeister; 14.07.2014
comment
iOS7 поддерживает новое сокращение: [UIView performWithoutAnimation:<#^(void)actionsWithoutAnimation#>]; - person k06a; 24.12.2014
comment
7 с половиной лет спустя, все еще полезно. - person Hector Matos; 22.04.2015
comment
7 лет, 7 месяцев и 17 дней спустя: все еще полезно. Спасибо! - person kanobius; 08.06.2016
comment
большой палец вверх 9 лет спустя - person nshuman; 09.03.2017
comment
Да!! палец вверх 9 лет спустя! - person vilanovi; 13.10.2017
comment
ребята @vilanovi и т. д., 12 лет спустя это неправильно :) в наши дни вы делаете это: stackoverflow.com/a/56980329/294884 - person Fattie; 22.01.2020

Расширение Swift 3:

extension CALayer {
    class func performWithoutAnimation(_ actionsWithoutAnimation: () -> Void){
        CATransaction.begin()
        CATransaction.setValue(true, forKey: kCATransactionDisableActions)
        actionsWithoutAnimation()
        CATransaction.commit()
    }
}

Использование :

CALayer.performWithoutAnimation(){
    someLayer.position = newPosition
}
person CryingHippo    schedule 27.11.2015
comment
Полезно добавить атрибут @noescape в блок, чтобы разрешить (и прояснить), что self не требуется в блоке - person Andrew; 03.08.2016

Вы также можете использовать удобную функцию

[CATransaction setDisableActions:YES] 

также.

Примечание. Обязательно прочтите комментарии Йогева Шелли, чтобы понять любые возможные подводные камни.

person Biclops    schedule 13.09.2011
comment
Важно: это влияет на все CALayer, поэтому вы хотите повторно активировать действия после того, как закончите, то есть [CATransaction setDisableActions: YES] - person Yogev Shelly; 25.01.2012
comment
Черт, я должен был это сказать. Хороший сейв. Команда отключает анимацию до тех пор, пока не будет установлено значение NO или пока ядро ​​анимации графики не завершит цикл выполнения. Не уверен, что это подходящее слово: / Но спасибо, что прояснили это для всех. - person Biclops; 14.02.2012

Как предлагали другие, вы можете использовать CATransaction.
Проблема возникает из-за того, что CALayer по умолчанию имеет длительность неявной анимации 0,25 секунды.

Таким образом, более простой (на мой взгляд) альтернативой setDisableActions является использование setAnimationDuration со значением 0.0.

[CATransaction begin];
[CATransaction setAnimationDuration:0.0];
layer.position = CGPointMake(x, y);
[CATransaction commit];
person So Over It    schedule 05.05.2013
comment
Легко запомнить, легко понять, когда вы перечитываете код, и легче набирать. Спасибо! - person Mr. T; 11.05.2013

Объединяя здесь предыдущие ответы для Swift 4, чтобы четко указать продолжительность анимации ...

extension CALayer
{
    class func perform(withDuration duration: Double, actions: () -> Void) {
        CATransaction.begin()
        CATransaction.setAnimationDuration(duration)
        actions()
        CATransaction.commit()
    }
}

Использование...

CALayer.perform(withDuration: 0.0) {
            aLayer.frame = aFrame
        }
person Giles    schedule 22.11.2018