Saya punya layer dengan beberapa kode gambar kompleks di -drawInContext: method. Saya mencoba meminimalkan jumlah gambar yang harus saya lakukan, jadi saya menggunakan -setNeedsDisplayInRect: untuk memperbarui hanya bagian yang diubah. Ini bekerja dengan baik. Namun, ketika sistem grafis memperbarui lapisan saya, itu beralih dari yang lama ke gambar baru menggunakan cross-fade. Saya ingin beralih secara instan.
Saya sudah mencoba menggunakan CATransaction untuk mematikan tindakan dan mengatur durasinya ke nol, dan tidak berhasil. Berikut kode yang saya gunakan:
[CATransaction begin];
[CATransaction setDisableActions: YES];
[self setNeedsDisplayInRect: rect];
[CATransaction commit];
Apakah ada metode berbeda pada CATransaction yang harus saya gunakan sebagai gantinya (Saya juga mencoba -setValue: forKey: dengan kCATransactionDisableActions, hasil yang sama).
iphone
ios
core-animation
calayer
Ben Gottlieb
sumber
sumber
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ });
Jawaban:
Anda dapat melakukan ini dengan mengatur kamus tindakan pada layer untuk kembali
[NSNull null]
sebagai animasi untuk tombol yang sesuai. Sebagai contoh, saya menggunakanuntuk menonaktifkan animasi fade in / out pada penyisipan atau perubahan sublayers dalam salah satu layer saya, serta perubahan ukuran dan isi layer. Saya percaya
contents
kuncinya adalah yang Anda cari untuk mencegah crossfade pada gambar yang diperbarui.Versi cepat:
sumber
@"position"
tombol.@"hidden"
properti di kamus tindakan juga jika Anda mengubah visibilitas lapisan seperti itu dan ingin menonaktifkan animasi opacity.actionForKey:
gantinya), menemukanfontSize
,contents
,onLayout
danbounds
. Sepertinya Anda dapat menentukan kunci apa saja yang dapat Anda gunakan dalamsetValue:forKey:
metode, sebenarnya menentukan jalur kunci yang kompleks sepertibounds.size
.Juga:
sumber
//foo
dengan[self setNeedsDisplayInRect: rect]; [self displayIfNeeded];
untuk menjawab pertanyaan awal.[CATransaction setDisableActions:YES]
[CATransaction setDisableActions:YES]
adalah singkatan untuk hanya[CATransaction setValue:forKey:]
baris. Anda masih membutuhkanbegin
dancommit
garis.Saat Anda mengubah properti lapisan, CA biasanya membuat objek transaksi implisit untuk menghidupkan perubahan. Jika Anda tidak ingin menganimasikan perubahan, Anda dapat menonaktifkan animasi tersirat dengan membuat transaksi eksplisit dan mengatur properti kCATransactionDisableActions menjadi true .
Objektif-C
Cepat
sumber
Selain jawaban Brad Larson : untuk lapisan khusus (yang dibuat oleh Anda), Anda dapat menggunakan delegasi alih-alih memodifikasi
actions
kamus layer . Pendekatan ini lebih dinamis dan mungkin lebih berkinerja. Dan itu memungkinkan penonaktifan semua animasi implisit tanpa harus mendaftar semua kunci yang dapat dianimasikan.Sayangnya, tidak mungkin untuk menggunakan
UIView
s sebagai delegasi lapisan kustom, karena masingUIView
- masing sudah merupakan delegasi dari lapisannya sendiri. Tetapi Anda dapat menggunakan kelas pembantu sederhana seperti ini:Penggunaan (di dalam tampilan):
Terkadang, nyaman untuk memiliki pengontrol tampilan sebagai delegasi untuk sublayer khusus tampilan; dalam hal ini tidak perlu kelas pembantu, Anda dapat menerapkan
actionForLayer:forKey:
metode tepat di dalam controller.Catatan penting: jangan mencoba memodifikasi delegasi dari
UIView
lapisan yang mendasarinya (mis. Untuk mengaktifkan animasi tersirat) - hal-hal buruk akan terjadi :)Catatan: jika Anda ingin menghidupkan kembali (tidak menonaktifkan animasi untuk) layer redraw, tidak ada gunanya memasukkan
[CALayer setNeedsDisplayInRect:]
panggilan ke dalamCATransaction
, karena redrawing yang sebenarnya mungkin (dan mungkin akan) terjadi kadang-kadang nanti. Pendekatan yang baik adalah dengan menggunakan properti khusus, seperti yang dijelaskan dalam jawaban ini .sumber
CALayer
yang mencegahnoImplicitAnimations
bekerja. Mungkin Anda harus menandai jawaban Anda sendiri sebagai benar dan menjelaskan apa yang salah dengan lapisan itu?CALayer
contoh yang salah (saya punya dua pada saat itu).NSNull
tidak menerapkanCAAction
protokol dan ini bukan protokol yang hanya memiliki metode opsional. Kode ini juga macet dan Anda bahkan tidak dapat menerjemahkannya dengan cepat. Solusi yang lebih baik: Buat objek Anda sesuai denganCAAction
protokol (denganrunActionForKey:object:arguments:
metode kosong yang tidak melakukan apa-apa) dan kembaliself
sebagai ganti[NSNull null]
. Efek yang sama tetapi aman (tidak akan crash pasti) dan juga berfungsi di Swift.Inilah solusi yang lebih efisien, mirip dengan jawaban yang diterima tetapi untuk Swift . Untuk beberapa kasus itu akan lebih baik daripada membuat transaksi setiap kali Anda mengubah nilai yang merupakan masalah kinerja seperti yang telah disebutkan orang lain misalnya kasus penggunaan umum menyeret posisi layer sekitar 60fps.
Lihat dokumen apple untuk bagaimana tindakan layer diselesaikan . Melaksanakan delegasi akan melewati satu tingkat lagi dalam kaskade tetapi dalam kasus saya yang terlalu berantakan karena peringatan tentang delegasi perlu diatur ke UIView terkait .
Sunting: Diperbarui berkat komentator yang menunjukkan yang
NSNull
sesuaiCAAction
.sumber
NullAction
untuk Swift,NSNull
sesuaikan dengan yangCAAction
sudah ada sehingga Anda dapat melakukan hal yang sama dengan yang Anda lakukan pada tujuan C: layer.actions = ["position": NSNull ()]Berdasarkan jawaban Sam, dan kesulitan Simon ... tambahkan referensi delegasi setelah membuat CSShapeLayer:
... di tempat lain dalam file "m" ...
Pada dasarnya sama dengan Sam tanpa kemampuan untuk beralih melalui pengaturan variabel "disableImplicitAnimations" kustom. Lebih dari pendekatan "kawat keras".
sumber
Sebenarnya, saya tidak menemukan jawaban yang tepat. Metode yang memecahkan masalah bagi saya adalah ini:
Lalu Anda bisa menggunakan logika apa pun di dalamnya, untuk menonaktifkan animasi tertentu, tetapi karena saya ingin menghapus semuanya, saya mengembalikan nihil.
sumber
Untuk menonaktifkan animasi lapisan implisit di Swift
sumber
disableActions()
karena kedengarannya seperti melakukan hal yang sama, tetapi sebenarnya untuk mendapatkan nilai saat ini. Saya pikir itu ditandai@discardable
juga, membuat ini lebih sulit dikenali. Sumber: developer.apple.com/documentation/quartzcore/catransaction/…Menemukan metode sederhana untuk bertindak menonaktifkan di dalam
CATransaction
yang internal panggilansetValue:forKey:
untukkCATransactionDisableActions
kunci:Cepat:
sumber
Tambahkan ini ke kelas khusus tempat Anda menerapkan metode -drawRect (). Buat perubahan pada kode sesuai kebutuhan Anda, bagi saya 'opacity' melakukan trik untuk menghentikan animasi lintas-pudar.
sumber
Jika Anda perlu memperbaikinya dengan sangat cepat (tapi harus di-hack) mungkin perlu dilakukan (Swift):
sumber
view.layer?.actions = [:]
tidak benar-benar bekerja. Pengaturan kecepatannya jelek tapi berhasil.Diperbarui untuk cepat dan menonaktifkan hanya satu animasi properti implisit di iOS bukan MacOS
Contoh lain, dalam hal ini menghilangkan dua animasi implisit.
sumber
Pada iOS 7 ada metode kenyamanan yang melakukan hal ini:
sumber
Untuk menonaktifkan animasi (buram) yang menjengkelkan saat mengubah properti string dari CATextLayer, Anda dapat melakukan ini:
dan kemudian gunakan seperti itu (jangan lupa mengatur CATextLayer Anda dengan benar, misalnya font yang benar, dll.):
Anda dapat melihat pengaturan lengkap saya dari CATextLayer di sini:
Sekarang Anda dapat memperbarui caTextLayer.string sebanyak yang Anda inginkan =)
Terinspirasi oleh ini , dan jawaban ini .
sumber
Coba ini.
Peringatan
Jika Anda mengatur delegasi dari UITableView instance, kadang-kadang terjadi crash. (Mungkin scrollview's hittest disebut rekursif.)
sumber