2012-11-14 28 views
46

Tôi có một UIImageView được nhúng trong một UIView. Toàn bộ ứng dụng của tôi sử dụng AutoLayout, nhưng tôi muốn xóa constraints cho số UIImageView. Xcode sẽ không cho phép tôi xóa constraints, có cách nào để vô hiệu hóa chúng cho một đối tượng cụ thể không, đặt chúng thành 0, cái gì?Xóa các ràng buộc bố cục tự động cho đối tượng cụ thể

+0

Nếu bạn loại bỏ các ràng buộc, cách hiển thị chế độ xem hình ảnh? Công cụ bố trí sẽ biết vị trí đặt nó ở đâu? Bạn phải có đủ thông tin ràng buộc để đưa ra toàn bộ khung nhìn một cách rõ ràng. Bạn đang thực sự cố gắng đạt được điều gì? – jrturton

+0

Tôi muốn đổi kích thước chế độ xem hình ảnh bằng cử chỉ. Các ràng buộc bố cục tự động sẽ không cho phép cử chỉ chụm để làm cho chế độ xem hình ảnh nhỏ hơn. – Eric

+0

Chỉ cần rõ ràng .. đối với một tệp XIB cụ thể. Để ** tắt ** autolayout (tức là để "loại bỏ các Constraints thingy") chỉ cần nhấp vào ShowFileInspector, và chỉ cần bỏ chọn "autolayout". Mỗi mục trên xib giờ đây sẽ hoạt động giống như kiểu "cũ" (với "mũi tên dính" và vân vân.) – Fattie

Trả lời

86

Tôi đồng ý Xcode tự động bố trí là khủng khiếp để sử dụng nếu bạn muốn một cái gì đó đặc biệt ...

gì tôi sử dụng để loại bỏ những hạn chế programatically:

[detailsPhotoView removeConstraints:detailsPhotoView.constraints]; 
+0

Cảm ơn, điều này đã hiệu quả. Tôi đã xóa tất cả các ràng buộc khỏi chế độ xem và đặt lại chúng bằng ngôn ngữ định dạng trực quan; Đoạn mã trên được yêu cầu để loại bỏ các ràng buộc trước khi chỉ định riêng của bạn, nếu không xcode sẽ tiếp tục phàn nàn –

+0

Cũng nên nhớ một điều, nếu bạn đang cố gắng loại bỏ ràng buộc khỏi UIImageView thì hãy chắc chắn rằng bạn thêm chế độ xem đó theo mã. Không sử dụng IBoutlet vì điều đó dường như không hề ảnh hưởng đến mã setFrame của bạn. Tôi chỉ chạy vào crap này. –

6

Bạn không thể không có trở ngại - bạn phải có đủ những hạn chế tại chỗ để rõ ràng kích thước và vị trí của mỗi điểm

Bạn thể tạo một cái nhìn thay đổi kích thước được lát bằng Autolayout.

Ví dụ: trong trường hợp của bạn, bạn có thể tạo các ràng buộc định vị - giả sử, ghim trung tâm của chế độ xem hình ảnh theo chiều ngang và chiều dọc vào tâm của người giám sát của nó.

Bạn cũng có thể tạo các hạn chế về kích thước, theo chiều ngang và chiều dọc. Xem câu trả lời của tôi here để biết cách thực hiện việc này. Tạo các cửa hàng cho hai ràng buộc này (nếu sử dụng trình tạo giao diện). Bạn có thể có giới hạn chiều cao và chiều rộng của một số cụ thể hoặc sử dụng hệ số để tạo tỷ lệ khung hình cố định.

Để phản hồi cử chỉ chụm, bạn có thể điều chỉnh các thuộc tính .constant của hai giới hạn kích thước và gọi setNeedsLayout. Điều này sẽ thay đổi kích thước chế độ xem hình ảnh của bạn trong khi vẫn giữ được trung tâm của nó.

Nếu bạn thực hiện đề xuất tỷ lệ khung hình cố định ở trên, việc thay đổi kích thước chế độ xem bằng các ràng buộc thực sự đơn giản hơn nhiều so với việc đặt khung.

+0

Tôi không muốn giữ bất cứ thứ gì được ghim trong vùng chứa UIView này. Tôi muốn imageView (một trong UIView) để có thể được chèn, di chuyển, panned vv mà không cần ghim bất cứ điều gì hoặc có bất kỳ hạn chế kích thước. Tôi sẽ đặt những hằng số nào cho điều đó? Tôi dường như không thể đạt được ngay ý nghĩ của mình về việc loại bỏ mọi ràng buộc. – Eric

+0

Nếu bạn muốn nó được di chuyển cũng như thay đổi kích cỡ, thì bạn cần các ràng buộc định vị mà bạn cũng có các cửa hàng mà bạn có thể sửa đổi trong mã theo cách tương tự như tôi mô tả các ràng buộc kích thước ở trên. Bạn _can't_ không có ràng buộc - bạn phải có đủ ràng buộc để thay đổi kích thước rõ ràng và định vị mọi khung nhìn. – jrturton

+0

Bạn sẽ thêm điều này dưới dạng chỉnh sửa để bạn trả lời: bạn phải có đủ ràng buộc để đặt kích thước rõ ràng và định vị mọi chế độ xem. Sau đó, tôi sẽ chấp nhận nó. – Eric

8

Có hai vấn đề riêng biệt ở đây:

  1. Làm thế nào để sử dụng Xcode để thiết lập một UIImageView mà không hạn chế
  2. Làm thế nào để cho phép các UIImageView được gay gắt và/hoặc thay đổi kích cỡ khi bố trí của nó được xử lý bởi các ràng buộc.

Về (1), jturton là chính xác. Miễn là bạn đã bật bố cục tự động trong Xcode, Xcode sẽ đảm bảo/yêu cầu có đủ ràng buộc để xác định duy nhất kích thước và vị trí của chế độ xem của bạn.

Nếu bạn không chỉ định đủ ràng buộc trong Xcode (thông qua "ràng buộc người dùng" xuất hiện màu xanh trong trình kiểm tra bố cục), thì Xcode sẽ thêm các ràng buộc mới mà nó đoán (xuất hiện màu tím) cho đến khi có đủ các ràng buộc để xác định bố cục.

Nếu UIImageView không có ràng buộc, bố cục của nó sẽ không được xác định, do đó bạn không thể thiết lập điều đó trong Xcode. Để khắc phục điều này, những gì bạn nên làm là sử dụng Xcode để thiết lập IBOutlets cho tất cả các ràng buộc bạn muốn loại bỏ, và sau đó trong UIView của awakeFromNib: hoặc trong viewView UIDiewController của bạn: bạn tự loại bỏ các ràng buộc bằng cách gọi removeConstraints :.

Tuy nhiên, bố cục của UIImageView chưa được xác định. Vì vậy, tại thời điểm này, bạn sẽ muốn tự thêm các ràng buộc mới cho phép bạn di chuyển và thay đổi kích cỡ UIImageView, điều này đưa chúng ta đến câu hỏi (2).

Về (2), cách đổi kích thước & di chuyển chế độ xem có bố cục được xác định bằng các ràng buộc, câu trả lời là thiết lập công cụ nhận dạng cử chỉ như thường lệ để phát hiện các cử chỉ di chuyển. sửa đổi khung nhìn, họ phải sửa đổi tham số constant của NSLayoutConstraint xác định khung của UIImageView và sau đó gọi layoutIfNeeded:, điều này sẽ làm cho hệ thống bố trí dịch ngay lập tức ràng buộc đã sửa đổi đó thành một khung mới. Ví dụ:

Ví dụ: giả sử bạn muốn thao tác UIImageView với một tập hợp các ràng buộc bố cục rất giống với setFrame quen thuộc: cuộc gọi. Trong trường hợp đó, sau khi gỡ bỏ các ràng buộc thiết lập bởi Xcode, bạn có thể thêm các ràng buộc vào khung nhìn xác định chiều rộng, chiều cao và không gian của nó từ phía trên và bên trái của superview. Sau đó, trình xử lý hành động cho trình nhận dạng cử chỉ của bạn sẽ chỉ cập nhật thông số không đổi của trình nhận dạng cử chỉ pacer và trình nhận dạng cử chỉ chụm của bạn chỉ có thể cập nhật tham số cố định của giới hạn chiều cao và chiều rộng.

Một cách khác để thực hiện (2), giống như dưới mui xe nhưng có thể dễ dàng hơn trong thực tế, là đặt translatesAutoresizingMaskIntoConstraints=YES. Điều này sẽ làm hai việc. Nó sẽ gây ra hệ thống bố trí tự động để tự động tạo ra các ràng buộc trong superview của khung nhìn dựa trên autoresizingMask của khung nhìn. Thứ hai - quan trọng! - nó sẽ làm cho hệ thống bố trí tự động dịch các cuộc gọi đến setFrame: thành sửa đổi các ràng buộc đó.

+2

Có một PITA về việc loại bỏ các ràng buộc: bạn cần phải loại bỏ một ràng buộc khỏi khung nhìn "lưu trữ" nó. Ví dụ. nếu bạn có và xem hình ảnh bên trong một khung nhìn cuộn và một ràng buộc giữa chúng, thì đó là cuộn lưu trữ nó.Ràng buộc sẽ không có mặt trong thuộc tính 'constraints' của khung nhìn, gọi' removeConstraint: 'trên khung nhìn hình ảnh sẽ được bỏ qua âm thầm, và không có cách nào để có được khung nhìn máy chủ từ chính bản thân ràng buộc. Vì vậy, bạn phải có các cửa hàng cho cả hai dạng xem cuộn và ràng buộc và đặc biệt gọi là '[self.scrollView removeConstraint: self.constraint]'. Argh! –

24

Trong XCode 5 có một tùy chọn trong khi chỉnh sửa ràng buộc 'Hủy bỏ tại thời gian xây dựng'. Nếu điều này được kích hoạt, ràng buộc sẽ tự động bị xóa trong thời gian chạy. Tùy chọn này là để giữ cho Interface Builder vui vẻ nếu bạn không muốn những ràng buộc cụ thể.

+0

Câu trả lời hay nhất, ngắn gọn và chính xác. – Borzh

+0

Trong XCode 6, bây giờ được gọi là Kích thước nội tại với tùy chọn được đặt thành Trình giữ chỗ. – ChrisStillwell

5

bạn có thể gọi

[yourElement removeFromSuperview]; 

và sau đó gọi

[yourSuperview addSubview:yourElement]; 

để loại bỏ tất cả các hạn chế từ yourElement và thêm nó trở lại xem.

Điều đáng nói rằng nếu bạn đang làm việc ở trên vào một cái gì đó giống như một loại UIView hoặc gia hạn, bạn cần phải lưu một tham chiếu đến SuperView của quan điểm trước khi tháo từ SuperView:

var theSuperview = self.superview 
self.removeFromSuperview() 
theSuperview?.addSubview(self) 

Bạn cũng có thể cần để làm cho yourElement mạnh mẽ thay vì yếu kể từ khi loại bỏ khỏi superview có khả năng có thể khiến bạn mất một tham chiếu đến nó.

+0

Tôi có một đối tượng tùy chỉnh object.view rằng sẽ không làm theo phương pháp removeConstraints. Điều này giải quyết nó tuyệt vời. Không có cảnh báo và hành vi được xác định theo chương trình chính xác như tôi đã hy vọng. Cảm ơn Adam! –

4

Nếu bạn chỉ muốn xóa chế độ xem khỏi cấu trúc phân cấp, chỉ cần gọi [theView removeFromSuperview]. Mọi ràng buộc ảnh hưởng đến nó cũng sẽ bị xóa.

Tuy nhiên, đôi khi bạn cũng có thể muốn đặt chế độ xem lại, khi có tạm thời xóa nó.

Để đạt được điều này, tôi sử dụng danh mục sau trên UIView.Nó đi lên hệ thống phân cấp khung nhìn từ chế độ xem v đến một số chế độ xem vùng chứa cuối cùng c (thường là chế độ xem gốc của trình điều khiển chế độ xem của bạn) và loại bỏ các ràng buộc bên ngoài là v. Đây là những ràng buộc là anh chị em với số v, chứ không phải là những ràng buộc chỉ ảnh hưởng đến con của v. Bạn có thể ẩn v.

-(NSArray*) stealExternalConstraintsUpToView: (UIView*) superview 
{ 
    NSMutableArray *const constraints = [NSMutableArray new]; 

    UIView *searchView = self; 
    while(searchView.superview && searchView!= superview) 
    { 
     searchView = searchView.superview; 

     NSArray *const affectingConstraints = 
     [searchView.constraints filteredArrayUsingPredicate: 
     [NSPredicate predicateWithBlock:^BOOL(NSLayoutConstraint *constraint, NSDictionary *bindings) 
      { 
       return constraint.firstItem == self || constraint.secondItem == self; 
      }]]; 

     [searchView removeConstraints: affectingConstraints]; 
     [constraints addObjectsFromArray: affectingConstraints]; 
    } 

    return constraints; 
} 

Phương thức này trả lại các ràng buộc đã xóa trong mảng mà bạn có thể giữ ở đâu đó để sau này bạn có thể thêm trở ngại.

Sử dụng nó một chút như thế này ...

NSArray *const removedConstraints = [viewToHide stealExternalConstraintsUpToView: self.view]; 
[viewToHide setHidden: YES]; 

Và sau này, đặt những hạn chế lại.

Kể từ iOS 8, bạn không cần phải suy nghĩ về nơi đặt các ràng buộc. Chỉ cần sử dụng tính năng này…

[NSLayoutConstraint activateConstraints: removedConstraints]; 
[viewToHide setHidden: NO]; 

Với các phiên bản iOS cũ hơn, bạn không cần phải suy nghĩ kỹ về nơi để thêm trở ngại. Sau đó ném vào bộ điều khiển self.view. Các ràng buộc được cung cấp nằm trong số a giám sát tất cả các chế độ xem mà chúng ảnh hưởng, chúng sẽ hoạt động.

[self.view addConstraints: removedConstraints]; 
[viewToHide setHidden: NO]; 
+0

activateConstraints có sẵn từ iOS 8 –

+0

@ b.zdybowicz - cảm ơn, đã cập nhật để làm rõ điều đó. Bất kỳ ai cũng có thể thực hiện chỉnh sửa, nhân tiện - đôi khi chúng được kiểm duyệt. – Benjohn

Các vấn đề liên quan