Saya memperbarui aplikasi lama dengan AdBannerView
dan ketika tidak ada iklan, itu akan hilang dari layar. Ketika ada iklan, iklan itu akan muncul di layar. Hal-hal dasar.
Gaya lama, saya mengatur bingkai di blok animasi. Gaya baru, saya memiliki IBOutlet
batasan tata letak otomatis yang menentukan Y
posisi, dalam hal ini jarak dari bagian bawah superview, dan memodifikasi konstanta:
- (void)moveBannerOffScreen {
[UIView animateWithDuration:5 animations:^{
_addBannerDistanceFromBottomConstraint.constant = -32;
}];
bannerIsVisible = FALSE;
}
- (void)moveBannerOnScreen {
[UIView animateWithDuration:5 animations:^{
_addBannerDistanceFromBottomConstraint.constant = 0;
}];
bannerIsVisible = TRUE;
}
Dan spanduk bergerak, persis seperti yang diharapkan, tetapi tidak ada animasi.
UPDATE: Saya menonton kembali WWDC 12 berbicara Best Practices for Mastering Auto Layout yang mencakup animasi. Ini membahas cara memperbarui kendala menggunakan CoreAnimation :
Saya sudah mencoba dengan kode berikut, tetapi mendapatkan hasil yang sama persis:
- (void)moveBannerOffScreen {
_addBannerDistanceFromBottomConstraint.constant = -32;
[UIView animateWithDuration:2 animations:^{
[self.view setNeedsLayout];
}];
bannerIsVisible = FALSE;
}
- (void)moveBannerOnScreen {
_addBannerDistanceFromBottomConstraint.constant = 0;
[UIView animateWithDuration:2 animations:^{
[self.view setNeedsLayout];
}];
bannerIsVisible = TRUE;
}
Di samping catatan, saya telah memeriksa beberapa kali dan ini sedang dieksekusi di utas utama .
Jawaban:
Dua catatan penting:
Anda perlu menelepon
layoutIfNeeded
dalam blok animasi. Apple sebenarnya merekomendasikan Anda untuk memanggilnya sekali sebelum blok animasi untuk memastikan bahwa semua operasi tata letak yang tertunda telah selesaiAnda perlu menyebutnya secara khusus pada tampilan induk (mis.
self.view
), Bukan tampilan anak yang memiliki batasan yang melekat padanya. Melakukan hal itu akan memperbarui semua pandangan terbatas, termasuk menjiwai pandangan lain yang mungkin dibatasi pada pandangan bahwa Anda mengubah batasan (misalnya B melihat melekat pada bagian bawah Tampilan A dan Anda baru saja mengubah offset atas Tampilan A dan Anda ingin Lihat B untuk menghidupkan dengan itu)Coba ini:
Objektif-C
Cepat 3
sumber
setNeedsLayout
daripada meneleponlayoutIfNeeded
. Saya sedikit ngeri dengan berapa jam yang saya habiskan tanpa memperhatikan saya baru saja mengetik nama metode yang salah.Saya menghargai jawaban yang diberikan, tetapi saya pikir akan lebih baik untuk membawanya sedikit lebih jauh.
Animasi blok dasar dari dokumentasi
tapi sungguh ini skenario yang sangat sederhana. Bagaimana jika saya ingin menghidupkan kendala subview melalui
updateConstraints
metode ini?Blok animasi yang memanggil metode pembaruan tampilan kendala
Metode updateConstraints ditimpa dalam subkelas UIView dan harus memanggil super di akhir metode.
Panduan AutoLayout menyisakan banyak yang diinginkan tetapi layak dibaca. Saya sendiri menggunakan ini sebagai bagian dari
UISwitch
yang mengubah subview dengan sepasangUITextField
s dengan animasi runtuh sederhana dan halus (panjang 0,2 detik). Kendala untuk subview sedang ditangani dalam metode updateConstraint subclass UIView seperti yang dijelaskan di atas.sumber
self.view
(dan bukan pada subview dari tampilan itu), panggilanupdateConstraintsIfNeeded
tidak diperlukan (karenasetNeedsLayout
juga pemicuupdateConstraints
dari view itu). Mungkin sepele untuk yang paling, tapi itu bukan untuk saya sampai sekarang;)Secara umum, Anda hanya perlu memperbarui batasan dan memanggil
layoutIfNeeded
bagian dalam blok animasi. Ini dapat berupa mengubah.constant
properti dariNSLayoutConstraint
, menambahkan batasan penghapusan (iOS 7), atau mengubah.active
properti batasan (iOS 8 & 9).Kode sampel:
Pengaturan sampel:
Kontroversi
Ada beberapa pertanyaan tentang apakah batasan harus diubah sebelum blok animasi, atau di dalamnya (lihat jawaban sebelumnya).
Berikut ini adalah percakapan Twitter antara Martin Pilkington yang mengajar iOS, dan Ken Ferry yang menulis Auto Layout. Ken menjelaskan bahwa meskipun mengubah konstanta di luar blok animasi saat ini dapat berfungsi, itu tidak aman dan mereka harus benar-benar berubah di dalam blok animasi. https://twitter.com/kongtomorrow/status/440627401018466305
Animasi:
Proyek Sampel
Berikut adalah proyek sederhana yang menunjukkan bagaimana tampilan dapat dianimasikan. Itu menggunakan Objective C dan menjiwai tampilan dengan mengubah
.active
properti dari beberapa kendala. https://github.com/shepting/SampleAutoLayoutAnimationsumber
sumber
Solusi Swift 4
UIView.animate
Tiga langkah sederhana:
Ubah kendala, misalnya:
Katakan pada yang mengandung
view
bahwa tata letaknya kotor dan bahwa autolayout harus menghitung ulang tata letak:Dalam blok animasi beri tahu tata letak untuk menghitung ulang tata letak, yang setara dengan pengaturan bingkai secara langsung (dalam hal ini autolayout akan mengatur bingkai):
Contoh lengkap yang paling sederhana:
Sidenote
Ada langkah 0 opsional - sebelum mengubah batasan Anda mungkin ingin memanggil
self.view.layoutIfNeeded()
untuk memastikan bahwa titik awal untuk animasi adalah dari negara dengan batasan lama diterapkan (jika ada beberapa perubahan kendala lain yang tidak boleh dimasukkan dalam animasi ):UIViewPropertyAnimator
Karena dengan iOS 10 kami mendapat mekanisme animasi baru -
UIViewPropertyAnimator
, kita harus tahu bahwa pada dasarnya mekanisme yang sama berlaku untuk itu. Langkah-langkahnya pada dasarnya sama:Karena
animator
ini adalah enkapsulasi dari animasi, kita dapat menyimpan referensi untuk itu dan menyebutnya nanti. Namun, karena di blok animasi kami hanya memberitahu autolayout untuk menghitung ulang frame, kami harus mengubah batasan sebelum memanggilstartAnimation
. Karena itu sesuatu seperti ini dimungkinkan:Urutan untuk mengubah batasan dan memulai animator adalah penting - jika kita hanya mengubah batasan dan meninggalkan animator kita untuk beberapa saat kemudian, siklus redraw berikutnya dapat meminta perhitungan ulang autolayout dan perubahan tidak akan dianimasikan.
Juga, ingatlah bahwa animator tunggal tidak dapat digunakan kembali - setelah Anda menjalankannya, Anda tidak dapat "menjalankannya kembali". Jadi saya kira tidak ada alasan yang tepat untuk menjaga animator tetap ada, kecuali kita menggunakannya untuk mengendalikan animasi interaktif.
sumber
Storyboard, Kode, Tips dan beberapa Gotcha
Jawaban lainnya baik-baik saja tetapi yang ini menyoroti beberapa gotcha yang cukup penting dari kendala animasi menggunakan contoh terbaru. Saya telah melalui banyak variasi sebelum saya menyadari hal berikut:
Buat batasan yang ingin Anda targetkan ke variabel Kelas untuk menyimpan referensi yang kuat. Di Swift saya menggunakan variabel malas:
Setelah beberapa percobaan saya mencatat bahwa satu HARUS mendapatkan kendala dari tampilan DI ATAS (alias superview) dua pandangan di mana kendala didefinisikan. Dalam contoh di bawah ini (MNGStarRating dan UIWebView adalah dua jenis item yang saya buat menjadi penghalang, dan mereka adalah subview dalam self.view).
Filter Chaining
Saya memanfaatkan metode filter Swift untuk memisahkan batasan yang diinginkan yang akan berfungsi sebagai titik belok. Satu juga bisa menjadi jauh lebih rumit tetapi filter melakukan pekerjaan yang bagus di sini.
Kendala Animasi Menggunakan Swift
Dengan asumsi Anda membuat properti untuk difilter dengan kriteria yang akurat dan sampai ke titik belok spesifik untuk animasi Anda (tentu saja Anda juga bisa memfilter untuk array dan loop melalui jika Anda memerlukan beberapa kendala):
....
Lain kali...
Banyak belokan yang salah
Catatan-catatan ini benar-benar seperangkat kiat yang saya tulis sendiri. Saya melakukan semua yang tidak boleh dilakukan secara pribadi dan menyakitkan. Semoga panduan ini dapat membantu orang lain.
Watch out for zPosisi. Terkadang ketika tidak ada yang tampaknya terjadi, Anda harus menyembunyikan beberapa tampilan lain atau menggunakan tampilan debugger untuk menemukan tampilan animasi Anda. Saya bahkan telah menemukan kasus di mana Atribut Runtime yang Ditentukan Pengguna hilang dalam xml storyboard dan menyebabkan tampilan animasi yang tercakup (saat bekerja).
Selalu luangkan waktu sebentar untuk membaca dokumentasi (baru dan lama), Bantuan Cepat, dan tajuk. Apple terus membuat banyak perubahan untuk mengelola kendala AutoLayout dengan lebih baik (lihat tampilan tumpukan). Atau setidaknya Cookbook AutoLayout . Ingatlah bahwa kadang-kadang solusi terbaik ada di dokumentasi / video yang lebih lama.
Bermain-main dengan nilai-nilai dalam animasi dan pertimbangkan untuk menggunakan varian animateWithDuration lainnya.
Jangan hardcode nilai tata letak khusus sebagai kriteria untuk menentukan perubahan konstanta lain, alih-alih gunakan nilai yang memungkinkan Anda untuk menentukan lokasi tampilan.
CGRectContainsRect
adalah salah satu contohnyalet viewMargins = self.webview.layoutMarginsGuide
: misalnyaContoh Cepat Solusi untuk DIHINDARI saat menggunakan Storyboard
Jika Anda lupa salah satu dari tips ini atau yang lebih sederhana seperti di mana menambahkan layoutIfNeeded, kemungkinan besar tidak akan terjadi: Dalam hal ini Anda mungkin memiliki solusi setengah matang seperti ini:
Cuplikan dari Panduan AutoLayout (perhatikan bahwa cuplikan kedua adalah untuk menggunakan OS X). BTW - Ini tidak lagi dalam panduan saat ini sejauh yang saya bisa lihat. Teknik yang disukai terus berkembang.
Animasi Perubahan yang Dibuat oleh Tata Letak Otomatis
Jika Anda membutuhkan kontrol penuh atas perubahan yang dibuat oleh Auto Layout, Anda harus membuat perubahan kendala secara terprogram. Konsep dasarnya sama untuk iOS dan OS X, tetapi ada beberapa perbedaan kecil.
Di aplikasi iOS, kode Anda akan terlihat seperti berikut:
Di OS X, gunakan kode berikut saat menggunakan animasi yang didukung layer:
Saat Anda tidak menggunakan animasi yang didukung layer, Anda harus menghidupkan konstanta menggunakan animator kendala:
Bagi mereka yang belajar lebih baik secara visual, lihat video awal ini dari Apple .
Perhatikan baik-baik
Seringkali dalam dokumentasi ada catatan kecil atau potongan kode yang mengarah ke ide yang lebih besar. Misalnya melampirkan batasan tata letak otomatis ke animator dinamis adalah ide besar.
Semoga Sukses dan Semoga The Force menyertai Anda.sumber
Solusi cepat:
sumber
Solusi Pengoperasian 100% Swift 3.1
saya telah membaca semua jawaban dan ingin membagikan kode dan hierarki baris yang telah saya gunakan di semua aplikasi saya untuk menghidupkannya dengan benar, Beberapa solusi di sini tidak berfungsi, Anda harus memeriksanya di perangkat yang lebih lambat misalnya iPhone 5 saat ini.
sumber
Saya mencoba untuk menghidupkan kendala dan tidak mudah menemukan penjelasan yang bagus.
Apa yang dikatakan jawaban lain sepenuhnya benar: Anda perlu menelepon ke
[self.view layoutIfNeeded];
dalamanimateWithDuration: animations:
. Namun, poin penting lainnya adalah memiliki petunjuk untuk setiapNSLayoutConstraint
Anda ingin menghidupkan.Saya membuat contoh di GitHub .
sumber
Solusi yang berfungsi dan baru diuji untuk Swift 3 dengan Xcode 8.3.3:
Perlu diingat bahwa self.calendarViewHeight adalah kendala yang disebut customView (CalendarView). Saya menelepon .layoutIfNeeded () di self.view dan BUKAN pada self.calendarView
Semoga bantuan ini.
sumber
Ada artikel yang membicarakan hal ini: http://weblog.invasivecode.com/post/42362079291/auto-layout-and-core-animation-auto-layout-was
Di mana, dia berkode seperti ini:
Semoga ini bisa membantu.
sumber
Dalam konteks animasi kendala, saya ingin menyebutkan situasi tertentu di mana saya animasi kendala segera dalam notifikasi keyboard_opened.
Batasan mendefinisikan ruang atas dari bidang teks ke atas wadah. Setelah pembukaan keyboard, saya hanya membagi konstanta dengan 2.
Saya tidak dapat mencapai animasi kendala halus yang terus-menerus secara langsung dalam notifikasi keyboard. Sekitar setengah kali tampilan hanya akan melompat ke posisi barunya - tanpa menjiwai.
Terjadi pada saya mungkin ada beberapa tata letak tambahan terjadi sebagai akibat dari pembukaan keyboard. Menambahkan blok dispatch_after sederhana dengan penundaan 10 ms membuat animasi berjalan setiap waktu - tidak ada lompatan.
sumber