Dapatkah saya menonaktifkan autolayout untuk subview tertentu saat runtime?


104

Saya memiliki tampilan yang perlu bingkai dimanipulasi secara terprogram - ini adalah jenis tampilan dokumen yang membungkus kontennya yang kemudian digulir dan diperbesar di sekitar tampilan super dengan memanipulasi asal bingkai. Autolayout bertarung dengan ini saat runtime.

Menonaktifkan autolayout sepenuhnya tampaknya sedikit sulit karena dapat digunakan secara wajar untuk menangani tata letak untuk tampilan lain. Sepertinya yang saya inginkan adalah semacam "kendala nol".

Jawaban:


168

Saya memiliki masalah yang sama. Tapi saya telah menyelesaikannya.
Ya, Anda dapat menonaktifkan tata letak otomatis saat runtime untuk hal tertentu UIView, daripada menonaktifkannya untuk seluruh xib atau storyboard yang disetel secara default di Xcode 4.3 dan yang lebih baru.

Setel translatesAutoresizingMaskIntoConstraintske YES, sebelum Anda menyetel bingkai subview Anda:

self.exampleView.translatesAutoresizingMaskIntoConstraints = YES;
self.exampleView.frame = CGRectMake(20, 20, 50, 50);

2
Ini sepertinya berlebihan untuk beberapa kasus yang lebih rumit dengan banyak tampilan. Untuk sesuatu yang sederhana seperti ini, ini tidak masalah.
esh

@MuhammadAamirALi menghapus subview dan menambahkannya kembali dapat menurunkan kinerja. Bisakah kita mengarsipkan solusi yang lebih baik?
Nhat Dinh

2
@DinhNhat saya mengklarifikasi jawabannya. Menghapus dan menambahkan kembali subview tidak perlu.
Leandros

5
Ini menunjukkan kepada saya peringatan: "Tidak dapat memenuhi kendala secara bersamaan."
NSPratik

1
Anda menyelamatkan hari saya ... menerjemahkanAutoresizingMaskIntoConstraints ... yang menciptakan properti seperti ini menggelengkan kepala
Tintenklecks

50

Saya memiliki masalah serupa di mana Autolayout menimpa beberapa pengaturan bingkai saya pada waktu berjalan (saya memiliki pandangan dinamis yang dalam beberapa kasus mendorong pengontrol tampilan baru ... mendorong dan kemudian menekan Kembali akan mengatur ulang tampilan awal).

Saya menyiasatinya dengan memasukkan kode manipulasi saya ke dalam viewDidLayoutSubviewsView Controller saya. Tampaknya ini dipanggil setelah kendala apa pun yang dipanggil mojo, tetapi sebelum viewDidAppear, jadi pengguna tidak bijaksana.


1
Tidak berfungsi untuk self.navigationItem.titleView. Masih tidak menghormati perubahan bingkai.
Henrik Erlandsson

1
Jika Anda mencoba mengacaukan bingkai tampilan judul, saya akan meletakkannya di dalam tampilan penampung dan menambahkan tampilan penampung sebagai tampilan kustom dari navigationItem.
jmstone617

2
Ini berhasil juga untuk saya. Saya telah menyia-nyiakan 2j: 22m membenturkan kepala saya ke dinding pepatah sebelum menemukan solusi ini.
TMc

Terima kasih sobat. Saya berada di hari kedua saya berjuang dengan masalah ini dan sekarang berhasil!
apostolov

28

Mungkin hanya menyetel translatesAutoresizingMaskIntoConstraintske YES(dan tidak menambahkan batasan tambahan yang memengaruhi tampilan itu) akan memungkinkan Anda menyetel bingkai tanpa melawan sistem tata letak otomatis.


17

Di iOS 8 Anda dapat mengatur NSLayoutConstraint menjadi aktif atau tidak. Jadi jika saya menggunakan pembuat antarmuka, saya menambahkan semua batasan saya ke OutletCollection dan kemudian mengaktifkan atau menonaktifkan menggunakan:

NSLayoutConstraint.deactivateConstraints(self.landscapeConstraintsPad)
NSLayoutConstraint.activateConstraints(self.portraitConstraintsPad)

Aplikasi khusus yang saya gunakan di sini memiliki batasan yang berbeda dalam mode potret dan lansekap dan saya mengaktifkan / menonaktifkan berdasarkan rotasi perangkat. Ini berarti saya dapat membuat beberapa perubahan tata letak yang kompleks, semuanya dalam pembuat antarmuka untuk kedua orientasi, dan masih menggunakan tata letak otomatis tanpa kode tata letak otomatis verbose.

Atau Anda dapat mengaktifkan / menonaktifkan menggunakan removeConstraints dan addConstraints.


Maaf telah membajak pertanyaan lama seperti itu, tetapi bolehkah saya bertanya bagaimana Anda berhasil menambahkan batasan tata letak untuk tata letak yang berbeda sejak awal? Sepertinya saya tidak dapat menemukan opsi di dalam pembuat antarmuka untuk mengaktifkan / menonaktifkan batasan. Atau apakah Anda hanya menambahkan batasan untuk kedua tata letak dan mengabaikan pembuat antarmuka yang mengeluh tentang batasan yang tidak valid (mengganti)?
Malte

Anda dapat melakukannya dengan menggunakan kelas ukuran: developer.apple.com/library/ios/recipes/… , tetapi saya tidak dapat melakukannya dengan cara ini karena saya juga mendukung iOS 7 dan kelas ukuran tidak sepenuhnya mendukung iOS 7 Saya melakukannya dengan menurunkan prioritas kendala yang berkonflik. Tidak ideal, tetapi mencegah peringatan itu. Saya pikir ini adalah cara saya melakukannya ....
bandejapaisa

9

Saya tidak tahu apakah ini akan membantu orang lain, tetapi saya menulis kategori untuk membuat ini nyaman karena saya sering melakukan ini.

UIView + DisableAutolayoutTemporally.h

#import <UIKit/UIKit.h>

@interface UIView (DisableAutolayoutTemporarily)

// the view as a parameter is a convenience so we don't have to always
// guard against strong-reference cycles
- (void)resizeWithBlock:(void (^)(UIView *view))block;

@end

UIView + DisableAutolayoutTemporally.m

#import "UIView+DisableAutoResizeTemporarily.h"
@implementation UIView (DisableAutoResizeTemporarily)

- (void)resizeWithBlock:(void (^)(UIView * view))block
{
    UIView *superview = self.superview;
    [self removeFromSuperview];
    [self setTranslatesAutoresizingMaskIntoConstraints:YES];
    __weak UIView *weakSelf = self;
    block(weakSelf);
    [superview addSubview:self];
}

@end

Saya menggunakannya seperti ini:

[cell.argumentLabel resizeWithBlock:^(UIView *view) {
    [view setFrame:frame];
}];

Semoga membantu.


Brilian! Saya menggunakan versi modifikasi dari kode Anda untuk menulis fungsi "hideControl" sederhana untuk setiap UIView. Ini pada dasarnya menyetel tinggi UIView ke 0, tetapi, yang terpenting, ini menggunakan kode Anda untuk membuat AutoLayout menanganinya dengan benar (tidak seperti menggunakan "someView.hidden = TRUE"). Jadi kontrol yang muncul di bawah kontrol tersembunyi, dan memiliki jarak vertikal yang terhubung dengannya, sekarang akan bergeser di layar untuk mengisi celah, di mana tampilan tersembunyi sebelumnya muncul.
Mike Gledhill

6

Anda dapat mengatur translatesAutoresizingMaskIntoConstraintsjenisnya Boolean, Value Yes di User Defined Runtime Attributes dari UIView yang Anda inginkan di xib / storyboard.


2
  • Buka proyek di 4.5
  • Pilih papan cerita
  • Buka pemeriksa file
  • Di bawah Interface Builder Document hapus centang 'Gunakan Autolayout'

Anda dapat membagi di beberapa papan cerita jika Anda ingin menggunakan tata letak otomatis untuk beberapa tampilan.


10
Itu menonaktifkan tata letak otomatis untuk seluruh papan cerita / ujung. Apa yang saya cari adalah cara (idealnya terprogram) untuk memiliki subview tertentu dalam storyboard / nib tidak menggunakan autolayout sementara membiarkan sisanya melakukan apa pun yang ditentukan storyboard / nib.
terriblememory

Anda dapat menggunakan beberapa papan cerita dan hanya memanggil yang dengan / tanpa tata letak otomatis sesuai kebutuhan: // Inisialisasi papan penyimpanan & pengontrol tampilan detail untuk tampilan UIStoryboard * sb = [UIStoryboard storyboardWithName: @ "Storyboard" bundel: [NSBundle mainBundle]]; DetailViewController * dvController = [sb instantiateViewControllerWithIdentifier: entry.viewName];
Mike Bobbitt

1

Bagi saya itu berhasil membuat subview secara terprogram, dalam kasus saya tata letak otomatis mengacaukan tampilan yang perlu saya putar di sekitar pusatnya tetapi begitu saya membuat tampilan ini secara terprogram, itu berfungsi.


1

Dalam pandangan saya, saya memiliki Label dan Teks. Label itu memiliki isyarat pan. Label bergerak dengan baik selama menyeret. Tapi ketika saya menggunakan keyboard kotak teks, label mengatur ulang posisinya ke lokasi asli yang ditentukan dalam tata letak otomatis. Masalah teratasi ketika saya menambahkan berikut ini dengan cepat untuk label. Saya menambahkan ini di viewWillAppear tetapi dapat ditambahkan cukup banyak di mana pun Anda memiliki akses ke bidang target.

self.captionUILabel.translatesAutoresizingMaskIntoConstraints = true

0

Ini terjadi pada saya dalam proyek tanpa papan cerita atau file xib. Semua kode 100%. Saya memiliki spanduk iklan di bagian bawah dan ingin batas tampilan berhenti di spanduk iklan. Tampilan akan berubah ukurannya secara otomatis setelah dimuat. Saya mencoba setiap resolusi di halaman ini tetapi tidak ada yang berhasil.

Saya akhirnya hanya membuat tampilan sub dengan ketinggian yang dipersingkat dan menempatkannya ke dalam tampilan utama pengontrol. Kemudian semua konten saya masuk ke dalam tampilan sub. Itu memecahkan masalah dengan sangat mudah tanpa melakukan apa pun yang terasa bertentangan dengan arus.

Saya berpikir jika Anda menginginkan tampilan yang ukurannya tidak normal yang mengisi jendela, maka Anda harus menggunakan tampilan sub untuk itu.


0

Saya mengalami skenario serupa, di mana saya bergabung dengan proyek yang dimulai dengan tata letak otomatis, tetapi saya perlu membuat penyesuaian dinamis ke beberapa tampilan. Inilah yang berhasil untuk saya:

  1. JANGAN memiliki tampilan atau komponen yang diletakkan di pembuat antarmuka.

  2. Tambahkan tampilan Anda secara terprogram, dimulai dengan alokasi / init dan menyetel bingkainya dengan tepat.

  3. Selesai.


0

Alih-alih menonaktifkan autolayout, saya hanya akan menghitung kendala baru dengan bingkai yang Anda ganti. Bagi saya itu adalah cara yang tepat. Jika Anda menyesuaikan komponen yang mengandalkan pembatas, sesuaikan.

Misalnya, jika Anda memiliki batasan vertikal 0 antara dua tampilan (myView dan otherView), dan Anda memiliki gerakan menggeser atau sesuatu yang menyesuaikan ketinggian myView, Anda dapat menghitung ulang batasan dengan nilai yang disesuaikan.

self.verticalConstraint.constant = newMyViewYOriginValue - (self.otherView.frame.origin.y + self.otherView.frame.size.height);
[self.myView needsUpdateConstraints];

0

Bagi Anda yang menggunakan tata letak otomatis, silakan lihat solusi saya di sini . Anda harus membuat @IBOutletbatasan yang ingin Anda sesuaikan dan kemudian mengubah konstanta mereka.


-16

jika itu file xib:

  1. pilih file .xib
  2. pilih "Pemilik File"
  3. tunjukkan Utilitas
  4. klik pada: "File Inspector"
  5. Di bawah "Interface Builder Document" nonaktifkan: "Use Autolayout"

1
Tidak, itu menonaktifkan tata letak otomatis untuk seluruh xib. Apa yang saya cari adalah cara untuk mengambil hanya satu subview tertentu dari sistem autolayout.
terriblememory
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.