UICollectionViewCell contentView'in Storyboard prototip hücresindeki (Xcode 6, iOS 8 SDK) çerçevesinin otomatik olarak yeniden boyutlandırılması sorunu yalnızca iOS 7'de çalışırken gerçekleşir


158

Xcode 6 Beta 3, iOS 8 SDK kullanıyorum. Swift kullanarak Hedef iOS 7.0 oluşturun. Lütfen aşağıdaki ekran görüntüleri ile sorunuma adım adım bakın.

Storyboard'da bir UICollectionView var. 1 Merkezde 1 etiket içeren UICollectionViewCell prototipi (otomatikleştirme kuralı yok). Mor arka plan Hücre tarafından çalışma zamanında oluşturulan bir contentView işaretlemek oldu sanırım. Bu görünüm sonunda UICollectionViewLayoutDelegate'im temel alınarak yeniden boyutlandırılacak, ancak iOS 7'de değil. Xcode 6 kullandığım ve sorunun yalnızca iOS 7'de oluştuğuna dikkat edin.

Uygulamayı iOS 8'de oluşturduğumda. Her şey yolunda.

Not: Mor contentView , Mavi yuvarlak köşeli UIButton'um.

http://i.stack.imgur.com/uDNDY.png

Bununla birlikte, iOS 7'de, Hücre içindeki tüm subView'ler aniden (0,0,50,50) çerçevesine küçülür ve artık Otomatikleştirme kuralımla hiçbir zaman uyumlu değildir.

http://i.stack.imgur.com/lOZH9.png

Bunun iOS 8 SDK veya Swift veya Xcode'da bir hata olduğunu varsayıyorum?


Güncelleme 1: Bu sorun hala resmi Xcode 6.0.1'de var! Etraftaki en iyi çözüm, hücrenin cellForItem öğesinde çerçeveyi ayarlayarak KoCMoHaBTa'nın aşağıda önerdiği gibidir (Yine de hücrenizi alt sınıflamanız gerekir). Bunun iOS 8 SDK ve iOS 7 arasında bir uyumsuzluk olduğu ortaya çıktı (ecotax'ın aşağıda Apple'dan alıntılanan cevabını kontrol edin).

Güncelleme 2: Bu kodu cellForItem'in başına yapıştırın ve her şey yolunda olmalıdır:

/** Xcode 6 on iOS 7 hot fix **/
cell.contentView.frame = cell.bounds;
cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
/** End of Xcode 6 on iOS 7 hot fix **/

1
Bu sorunun hala Xcode 6 Beta 5'te bulunduğunu öğrendim.
thkeen

2
Şu anda projemde bununla mücadele ediyorum. Xcode 5 kullanılarak oluşturulan iOS 7 ve iOS 8 iyi görünüyor. Xcode 6 beta 6 kullanılarak oluşturulan iOS 8 iyi görünüyor. Xcode 6 beta 6 kullanılarak oluşturulan iOS 7 açıklamakta olduğunuz sorunu yaşıyor. Reveal kullanarak benim UICollectionViewCell düzgün boyutlandırılmış görebiliyorum. Ancak hücrenin contentView öğesi, üst öğe olmasına rağmen, UICollectionViewCell'de Otomatik Boyutlandırma Alt Görünümleri açık olarak yeniden boyutlandırılmadı. ContentView öğesinin boyutu, film şeridinin boyutuna ayarlanır. Bu projede autolayout kullanmıyorum. Projem tamamen objektif-c.
Del Brown

2
Sadece bu sorunun Xcode 6 / iOS 8 GM tohumundan itibaren hala mevcut olduğunu eklemek istedim. @ DanielPlamann'ın contentViewhücre ile yeniden boyutlandırmaya zorlama cevabı , sorunu çözmek için iyi çalışıyor. İOS 8'de Apple'ın Interface Builder'da oluşturulduğunda hücre içeriği görünümlerinin işlenme şekli hakkında bir şey değiştirdiğini tahmin ediyorum (yine de biraz kara kutu). Ancak iOS 7'yi hedeflerken davranış değiştirmesi kesinlikle bir hatadır.
Stuart

Burada Xcode 6 GM, otomatik düzen ve uç tabanlı bir hücre için de geçerlidir. contentViewKenarları hücre kenarlarına sabitleyerek düzeltirim .
sergiou87

3
Xcode 6.1'i indirdim ancak yine de aynı sorunu simülatörde görüyorum.
Haitao Li

Yanıtlar:


169

contentView bozuk. Uyanıkken de düzeltilebilir

objc:

- (void)awakeFromNib {

    [super awakeFromNib];

    self.contentView.frame = self.bounds;
    self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}

swift3:

override func awakeFromNib() {
    super.awakeFromNib()

    self.contentView.frame = self.bounds
    self.contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}

3
Hile self.contentView.frame = self.bounds olmadan mı yaptı; İhtiyacım olduğunu mu düşünüyorsun? Yine de teşekkürler!
Michal Shatz

Merhaba Michal, sana katılıyorum. Ancak% 100 emin olmak için, sonraki iOS'larda nasıl ekleyeceğini daha iyi bence.
Igor Palaguta

5
Bu yanıtı seviyorum ama [süper awakeFromNib] çağırmanız gerekir; Ayrıca, iOS 7.1 ve daha azı için bir kontrol eklemeyi düşünüyorum, çünkü bu yeniden boyutlandırma maskelerinin eklenmesinin iOS8'deki varsayılan davranışı nasıl etkilediğinden emin değilim.
GingerBreadMane

Eğer uç veya film şeridi kullanmıyorsanız, ApplyLayoutAttributes'a koyarsanız da çalışır:
cetcet

Bu benim için işe yaramıyor. Ben Autolayout kullanmıyorum !! Herhangi bir yardım?
thatzprem

61

Aynı sorunla karşılaştım ve Apple DTS'den yardım istedim. Cevapları:

İOS 7'de hücrelerin içerik görünümleri, otomatikleştirme maskeleriyle kendilerini boyutlandırdı. İOS 8'de bu değiştirildi, hücreler otomatikleştirme maskelerini kullanmayı bıraktı ve layoutSubviews içindeki içerik görünümünü boyutlandırmaya başladı. İOS 8'de bir uç kodlanır ve ardından iOS 7'de kodu çözülürse, otomatikleştirme maskesi olmayan bir içerik görünümünüz olur ve kendisini boyutlandırmanın başka bir yolu yoktur. Dolayısıyla, hücrenin çerçevesini değiştirirseniz, içerik görünümü takip etmez.

İOS 7'ye geri dağıtılan uygulamaların, içerik görünümünün boyutunu boyutlandırarak, otomatikleştiren maskeler ekleyerek veya kısıtlamalar ekleyerek bu sorunu çözmesi gerekir.

Sanırım bu XCode 6'da bir hata değil, iOS 8 SDK ve iOS 7 SDK arasında bir uyumsuzluk anlamına geliyor, bu da Xcode 6'ya yükselttiğinizde sizi vuracak, çünkü otomatik olarak iOS 8 SDK'yı kullanmaya başlayacak.

Daha önce yorumladığım gibi, Daniel Plamann'ın benim için çalışmaları anlattığı geçici çözüm. Igor Palaguta ve KoCMoHaBTa tarafından tarif edilenler daha basit görünüyor ve Apple DTS'nin cevabını vermek mantıklı görünüyor, bu yüzden daha sonra deneyeceğim.


Bu ilginç, ama umarım hala düzeltirler. Bu davranış yalnızca iPhone 6 desteği ekleyen Xcode 6 GM'de tanıtıldı. Daha önceki betalarda iyi çalışıyordu. Bir projeyi fark ettikten sonra daha önceki bir beta sürümüne bile getirdim ve beklendiği gibi çalıştı. Umarım herkes bu konuda Apple ile hata dosyaları.
arton

@arton DTS'den yardım istediğim aynı gün hata raporu verdim. 18312246 kopyası olarak kapatıldı. Bunun ne kadar yardımcı olduğundan emin değilim.
ecotax

Etraftaki işi ContentView'i boyutlandırarak kullandım ve benim için çalışıyor. - (CGSize) collectionViewContentSize {return CGSizeMake (self.collectionView.bounds.size.width, self.collectionView.bounds.size.height); }
Jesús Hurtado

60

Aynı sorunla karşılaştım ve Apple'ın bir sonraki Xcode sürümü ile bu sorunu çözeceğini umuyorum. Bu arada bir geçici çözüm kullanıyorum. Benim içinde UICollectionViewCellalt sınıf Sadece geçersiz kıldık layoutSubviewsve gelen durumunda elle boyutu farklılık contentView boyutlandırmak collectionViewCellboyutuna.

- (void)layoutSubviews
{
  [super layoutSubviews];

  BOOL contentViewIsAutoresized = CGSizeEqualToSize(self.frame.size, self.contentView.frame.size);

  if( !contentViewIsAutoresized) {
    CGRect contentViewFrame = self.contentView.frame;
    contentViewFrame.size = self.frame.size;
    self.contentView.frame = contentViewFrame;
  }
}

Evet benzer bir çalışma kullandım ama aynı zamanda cellForItem / cellForRow da çalıştım.
2014'te

1
Bu en iyi çözümdür. Bunu cellForItem / cellForRow'a eklemek, cihazı döndürürseniz ve hücre boyutu değişirse garip yapaylıklara neden olur.
spybart

Selam! Bu kodla ilgili bir sorunum var. İlk kez, boole içeriğiViewIsAutoresized, film şeridi veya prototip hücresinden yüklüyse doğru olur. Yalnızca bir reloadData yaptığınızda, ikincisi doğru olacaktır. Yani gerçekten boyutu kontrol etmeniz gerekmez. Bunun yerine şunu yapın: self.contentView.frame = self.bounds;
thkeen

Onaylandı: layoutSubviews yalnızca hücre döndükten sonra çağrıldığından bunu cellForItem veya cellForRow'da yapmalıyız. Bundan önce yaptığınız şeyler çizim gibi yanlış hesaplanır.
14:18

1
Hm, belki [cell layoutIfNeeded];cellForItem veya cellForRow'a yerleştirmek daha iyidir ?
wtorsi

38

Başka bir çözüm, contentView'in boyutunu ve otomatikleştiren maskeleri -collectionView:cellForItemAtIndexPath:aşağıdaki gibi ayarlamaktır :

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

     static NSString *cellID = @"CellID";

     UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];

     // Set contentView's frame and autoresizingMask
     cell.contentView.frame = cell.bounds;
     cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;

     // Your custom code goes here

     return cell;
}

Otomatik yeniden boyutlandırma maskeleri kısıtlamalara çevrildiğinden, bu Otomatik Düzen ile de çalışır.


2
Bu, alt sınıflama olmadan herhangi bir hücre türüyle çalıştığı ve koleksiyon görünümünüzde birden fazla hücre türü kullandığınızda birden çok yerde değişiklik gerektirmediğinden üstün bir çözümdür.
nacross

6

Xcode 6.0.1'de content7 for UICollectionViewCell, iOS7 cihazları için bozuldu. UICollectionViewCell ve contentView öğelerine awakeFromNib veya init yöntemlerinde uygun kısıtlamalar eklenerek de düzeltilebilir.

        UIView *cellContentView = self.contentView;
        cellContentView.translatesAutoresizingMaskIntoConstraints = NO;

        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[cellContentView]|"
                                                                     options:0
                                                                     metrics:0
                                                                       views:NSDictionaryOfVariableBindings(cellContentView)]];
        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[cellContentView]|"
                                                                     options:0
                                                                     metrics:0
                                                                       views:NSDictionaryOfVariableBindings(cellContentView)]];

Sadece şimdi çalışıyor, sadece IOS 8 için yapmalısın ve her aykırmadan sonra çağırmalıyım! Ancak bu aynı zamanda ideal bir çözüm değildir, çünkü çoklu seçim görsel olarak olması gerektiği gibi çalışmaz ...
Renetik

En iyisi autolayout'u gerçekten kullanmaktır, bu
hatayla

Maske benim için çalışmıyor; ancak kısıtlamaları ayarlamak işe yarıyor!
entropid

4

Xcode 6 GM'de Xcode'un xib dosyalarını nib formatına nasıl derlediğiyle ilgili bir hata nedeniyle, bu belirtilen diğer geçici çözümlerden herhangi biri olmadan bu düzgün çalışmaz. Ben% 100 kesinlik için Xcode ile ilgili olduğunu söyleyemem ve çalışma zamanı ile ilgili olmak zorunda değilim, çok eminim - nasıl gösterebilirim:

  1. Build + Xcode 5.1'de uygulamayı çalıştırın.
  2. Simülatör uygulamasının dizinine gidin ve sorun yaşadığınız xib için derlenmiş .nib dosyasını kopyalayın.
  3. Build + Xcode 6 GM'de uygulamayı çalıştırın.
  4. Uygulamayı durdurun.
  5. Yeni oluşturulan uygulamanın simülatör klasöründeki .nib dosyasını Xcode 5.1 kullanılarak oluşturulan .nib dosyasıyla değiştirin
  6. Xcode değil, simülatörden uygulamayı yeniden başlatın.
  7. Bu .nib dosyasından yüklenen hücreniz beklendiği gibi çalışmalıdır.

Umarım bu soruyu okuyan herkes Apple'a bir Radar gönderir. Bu çok büyük bir sorundur ve son Xcode sürümünden önce ele alınması gerekir.

Düzenleme: ecotax'ın gönderisi ışığında , şimdi iOS 8 vs iOS 7'de bina arasındaki davranış farklarının doğrulandığını, ancak bir hata olmadığını söylemek için bunu güncellemek istedim. Bilgisayarımın 7'de oluşturulması, Apple'ın artık eklemediği bu işi yapmak için gereken içerik görünümüne otomatikleştirme maskesini eklediğinden hack'im sorunu çözdü.


Yasal olarak GM sürümünden farklı bir xCode yayınlayıp yayınlayamayacaklarından emin değilim
Mabedan

Haha hapse mi girecekler? = P Ama tüm ciddiyetle, emin olabilirler. Hatırlamıyorsanız Mavericks için çoklu GM sürümleri vardı. Çok yaygın değil ama olabilir.
Acey

4

Bu yazıdaki cevaplar, hiç anlamadığım şey neden işe yaradığı.

İlk olarak, iki "kural" vardır:

  1. Programlı oluşturulan görünümler için (Ör. [UIView new]), Mülkiyet translatesAutoresizingMaskIntoConstraintsolarak ayarlanırYES
  2. Arayüz Oluşturucu ile oluşturulmuş Görüntüleme, AutoLayout etkinken, mülkiyet olacak translatesAutoresizingMaskIntoConstraintskadar setNO

İkinci kural, kendisi için kısıtlama tanımlamadığınız en üst düzey görünümler için geçerli görünmemektedir. (Örn. İçerik görünümü)

Bir Storyboard hücresine bakarken, hücrenin contentViewaçıkta kalmadığına dikkat edin. contentViewApple 'ı "kontrol etmiyoruz" .

Film şeridi kaynak kodunu derinlemesine inceleyin ve contentViewhücrenin nasıl tanımlandığını görün:

<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">

Şimdi hücrenin alt görünümleri (dikkat edin translatesAutoresizingMaskIntoConstraints="NO"):

<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NaT-qJ-npL" userLabel="myCustomLabel">

contentViewO oluyor yoktur translatesAutoresizingMaskIntoConstraintsayarlı NO. Ayrıca, @ecotax'ın söylediklerinden dolayı düzen tanımından yoksundur .

Eğer içine contentViewbakarsak, otomatikleştiren bir maskesi var, ancak bunun tanımı yok: <autoresizingMask key="autoresizingMask"/>

Yani iki sonuç var:

  1. contentView translatesAutoresizingMaskIntoConstraintsolarak ayarlanmıştır YES.
  2. contentView düzen tanımından yoksun.

Bu bizi konuşulan iki çözüme götürür.

Otomatik yeniden boyutlandırma maskelerini manuel olarak şu dillerde ayarlayabilirsiniz awakeFromNib:

self.contentView.frame = cell.bounds;
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

Yoksa ayarlayabilirsiniz contentView translatesAutoresizingMaskIntoConstraintsiçin NOde awakeFromNibve de kısıtları tanımlamak - (void)updateConstraints.


4

Bu kabul edilen @ Igor'un cevabının Swift versiyonudur ve güzel cevap arkadaşınız için teşekkür ederiz.

İlk Goto sizin UICollectionViewCello sınıfın içinde olduğu gibi alt sınıf aşağıdaki kodu yapıştırın ve.

override func awakeFromNib() {
    super.awakeFromNib()
    self.contentView.frame = self.bounds
    self.contentView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
}

Bu arada Xcode 7.3.1 ve Swift 2.3 kullanıyorum. Çözüm, kusursuz çalışan iOS 9.3'te test edildi.

Teşekkürler, umarım bu yardımcı oldu.


Kötü İngilizcem için özür dilerim, "cazibe gibi çalışır" demek
istedim

@Aznix Sorun yok .. :)
onCompletion

2

Hızlıca, toplama görünümü hücre alt sınıfına aşağıdaki kodu yerleştirin:

override var bounds: CGRect {
  didSet {
    // Fix autolayout constraints broken in Xcode 6 GM + iOS 7.1
    self.contentView.frame = bounds
  }
}

Aradığım cevap buydu. Bu sorunu gidermek için Objective-C setBounds geçersiz kılmak için kullanılır (Swift nasıl yazacağından emin değildi). Teşekkür ederim :)
Matthew Cawley

1

Ayrıca contentViewiOS 8'de boyutlandırma ile ilgili sorunlar olduğunu buldum . Bu, döngüde çok geç ortaya konma eğilimindedir, bu da geçici kısıtlama çatışmalarına neden olabilir. Bunu çözmek için, aşağıdaki yöntemi bir kategoriye ekledim UICollectionViewCell:

- (void)fixupContentView
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 80100
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
    if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) {
        self.contentView.frame = self.bounds;
        self.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
    } else {
        [self layoutIfNeeded];
    }
#endif
#endif
}

Hücre ayıklandıktan sonra bu yöntem çağrılmalıdır.


Bu yöntemin otomatik olarak çağrılması ideal olur. Bunu sevmiyorum, ama bu donarak yapılabilir dequeueReusableCellWithReuseIdentifier:forIndexPath:.
phatmann

Apple, bu sorunu Xcode 6.1 GM'de (Build 6A1042b) iOS SDK'nın 8.1 sürümünde gidermiş gibi görünüyor. Bu nedenle 8.1 SDK kullanırken çalıştırmak için yukarıdaki kodu güncelledim. Ekibiniz Xcode 6.1'e taşındıktan sonra bu hack'i tamamen kaldırabilirsiniz.
phatmann

1

Bunu yaparken sabit:

override func layoutSubviews() {
   contentView.superview?.frame = bounds
   super.layoutSubviews()
}

bkz: burada


-1

Bu toplama görünümü hücresi için uçtaki "Alt görünümleri otomatikleştir" onay kutusunu işaretlediğinizden emin olun. Hem iOS 8 hem de iOS 7'de iyi çalışır.


Hayır değil. Bu, gömülü bir prototip hücredir.
thkeen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.