İOS11'de tuhaf uitableview davranışı. Hücreler gezinme itme animasyonuyla yukarı kaydırılır


116

Yakın zamanda bazı kodları yeni iOS 11 beta 5 SDK'ya taşıdım.

Şimdi UITableView'dan çok kafa karıştırıcı bir davranış alıyorum. Masa görünümünün kendisi o kadar da süslü değil. Özel hücrelerim var ama çoğu zaman sadece boyları için.

Görünüm denetleyicimi tablo görünümüyle ittiğimde, hücrelerin "yukarı kaydırıldığı" (veya muhtemelen tüm tablo görünümü çerçevesinin değiştirildiği) ve bas / aç gezinme animasyonu boyunca aşağıya indiği ek bir animasyon alıyorum. Lütfen gif'e bakın:

dalgalı masa

El ile oluşturmak tableviewiçinde loadViewTableview en Superview lider, sondaki, üst, alt eşit olacak şekilde yöntem ve kurulum otomatik düzen kısıtlamaları. Denetleme görünümü, görünüm denetleyicisinin kök görünümüdür.

Denetleyici itme kodunu görüntüle çok standarttır: self.navigationController?.pushViewController(notifVC, animated: true)

Aynı kod, iOS 10'da normal davranış sağlar.

Bana neyin yanlış olduğunu gösterebilir misin?

DÜZENLEME: Çok basit bir tableview kontrolörü yaptım ve aynı davranışı orada yeniden oluşturabilirim. Kod:

class VerySimpleTableViewController : UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
    }


    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 4
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

        cell.textLabel?.text = String(indexPath.row)
        cell.accessoryType = .disclosureIndicator

        return cell
    }


    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)

        let vc = VerySimpleTableViewController.init(style: .grouped)

        self.navigationController?.pushViewController(vc, animated: true)
    }
}

DÜZENLEME 2: UINavigationBar'ı özelleştirmeme sorunu daraltabildim. Bunun gibi bir özelleştirmem var:

rootNavController.navigationBar.setBackgroundImage(createFilledImage(withColor: .white, size: 1), for: .default)

nerede createFilledImageverilen boyut ve renk ile kare görüntü oluşturur.

Bu satırı yorumlarsam normal davranışıma geri dönerim.

Bu konudaki tüm düşüncelerimi takdir ediyorum.


Gezinme çubuğunun özelleştirilmesiyle ilgili bir sorun olmayabilir. Herhangi bir özelleştirme olmadan aynı sorunu yaşıyordum (kabul edilen cevap bunu çözdü). UITableViewController'ı kullanmak yerine manuel olarak bir alt görünüm olarak oluşturulduğunda iOS'un tablo görünümünü işleme biçimiyle ilgili bir sorun olabileceğini düşünüyorum.
Mark Leonard

2
Ben set sadece bu davranış görüyorum navigationBar.isTranslucentiçin falseaksi takdirde para cezası çalışır.
b_ray

5
Bu, iOS11 GM'de bir hata gibi görünüyor, bu sorunun Apple'dan biraz dikkat çekmesi için lütfen bu hata raporunu kopyalayın
b_ray

1
Bu sorun iOS 11.2 beta sürümünde çözülmüş gibi görünüyor. ContentInsetAdjustmentBehavior'ı asla olarak ayarlamazdım çünkü ekranın altında dolgu vermeyerek iPhone X kaydırma görünümlerini bozar. İçerik görünümünüzün alt kısmı, iPhone X'in ana "düğmesinin" altında kalır.
batu

Yanıtlar:


150

Bunun nedeni UIScrollView's (UITableView, UIScrollview'in bir alt sınıfıdır)contentInsetAdjustmentBehavior , .automaticvarsayılan olarak ayarlanan yeni özelliğidir .

Bu davranışı, etkilenen denetleyicilerin viewDidLoad'unda aşağıdaki kod parçacığı ile geçersiz kılabilirsiniz:

    tableView.contentInsetAdjustmentBehavior = .never

https://developer.apple.com/documentation/uikit/uiscrollview/2902261-contentinsetadjustmentbehavior


2
UIScrollViewContentInsetAdjustmentBehavior.automatic tanımına ilişkin bu yorum şöyle diyor: "... geriye dönük uyumluluk için ayrıca kaydırma görünümü bir görünüm denetleyicisine sahip olduğunda üst ve alt contentInset'i de ayarlayacaktır. görünüm kaydırılabilir ". Teorim, gezinti çubuğunun contentInset'inin arka plan görüntüsünü ayarlayarak etkilenmesi ve ardından dinamik olarak ayarlanmasıdır.
Maggy Hillen

8
Bunu film şeridi ile de yapabilirsiniz. Boyut Denetçisi -> İçerik Eklemeleri -> 'Asla' seçeneğini ayarlayın.
Woongbi Kim

4
İçeriğiniz sekme çubuğunun arkasına genişlerse, devre dışı bırakmak tableView.contentInsetAdjustmentBehaviorgirintileri bozacaktır.
kean

4
Ayrıca, bunu devre dışı bırakmak, kaydırma göstergesini yatay konumda iPhone X üzerindeki (üst gizmo) arkasına yerleştirir. Bu davranışın bütün amacı, kaydırma görünümlerinin içerik alanını, dikdörtgen olmayan ekranlarda görünebilecek şekilde ayarlamaktır. Sanırım bunu şu anda yalnızca iPhone X Sim'de görebiliyoruz.
PhoneyDeveloper

8
Bu sorun, iOS 11.2'de düzeltilmesi gereken gezinme geçişi sırasında görünüm denetleyicisinin görünümünün safeAreaInsets'inin yanlış ayarlandığı iOS 11'deki bir hatadan kaynaklanıyordu. Ayar contentInsetAdjustmentBehavioriçin .neverbüyük olasılıkla diğer istenmeyen yan etkileri olacaktır çünkü büyük bir geçici çözüm değildir. Bir geçici çözüm kullanırsanız, iOS sürümleri> = 11.2 için kaldırdığınızdan emin olmalısınız.
smileyborg

23

Maggy'nin cevabına ek olarak

AMAÇ-Cı

if (@available(iOS 11.0, *)) {
    scrollViewForView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}

Bu sorun, safeAreaInsetsiOS 11.2'de düzeltilmesi gereken gezinme geçişi sırasında görünüm denetleyicisinin görünümünün yanlış ayarlandığı iOS 11'deki bir hatadan kaynaklanıyordu . Ayar contentInsetAdjustmentBehavioriçin .neverbüyük olasılıkla diğer istenmeyen yan etkileri olacaktır çünkü büyük bir geçici çözüm değildir. Bir geçici çözüm kullanırsanız, iOS sürümleri> = 11.2 için kaldırdığınızdan emin olmalısınız.

smileyborg tarafından bahsedilen (Apple'da Yazılım Mühendisi)


6

Örneğin didFinishLaunchingWithOptions'da NSProxy'yi kullanarak bu davranışı uygulama genelinde bir kerede düzenleyebilirsiniz:

if (@available(iOS 11.0, *)) {
      [UIScrollView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} 

1
Bu, UIImagePickerController gibi sistemin denetleyicisini kıracak
galway

6

İOS 11'in ekleri otomatik olarak ayarlamasına izin verirken bu sorunu nasıl çözmeyi başardım . Ben kullanıyorum UITableViewController.

  • Film şeridinde (veya programlı olarak ) görünüm denetleyicinizde "Kenarları üst çubukların altına genişlet" ve "Opak çubukların altında kenarları genişlet" seçeneklerini seçin . Güvenli alan ekleri, görünümünüzün üst çubuğun altına girmesini engelleyecektir.
  • Film şeridinizdeki tablo görünümünüzdeki "Güvenli Alana Ekler" düğmesini kontrol edin. (veya tableView.insetsContentViewsToSafeArea = true) - Bu gerekli olmayabilir ama ben öyle yaptım.
  • İçeriğin ek ayar davranışını "Kaydırılabilir Eksenler" (veya tableView.contentInsetAdjustmentBehavior = .scrollableAxes) olarak ayarlayın - .alwaysişe yarayabilir ama ben test etmedim.

Her şey başarısız olursa denenecek bir şey daha:

viewSafeAreaInsetsDidChange UIViewControllerKaydırma görünümü girintilerini güvenli alan girintilerine ayarlamaya zorlamak için tablo görünümünü elde etmek için geçersiz kılma yöntemi. Bu, Maggy'nin cevabındaki 'Asla' ayarı ile bağlantılı.

- (void)viewSafeAreaInsetsDidChange {
    [super viewSafeAreaInsetsDidChange];
    self.tableView.contentInset = self.view.safeAreaInsets;
}

Not: self.tableViewve self.viewiçin aynı şey olmalıdırUITableViewController


Bu konudaki neredeyse her şeyi denedim ve bu benim için çalıştı. TabBarVC'ye gömülü TableViewVC. Teşekkür ederim!
Josh Wolff

3

Bu, amaçlanan davranıştan çok bir hata gibi görünüyor. Gezinme çubuğu yarı saydam olmadığında veya arka plan görüntüsü ayarlandığında gerçekleşir.

ContentInsetAdjustmentBehavior'ı. Hiçbir zaman olarak ayarlarsanız, iPhone X'de içerik eklemeleri doğru şekilde ayarlanmayacaktır, örneğin içerik kaydırma çubuklarının altındaki alt alana gidecektir.

İki şey yapmak gerekir:
1. push /
pop'da yukarı kaydırma hareketini engelleyin 2. iPhone X için gerekli olduğundan .automatic davranışını koruyun. Bu olmadan, örneğin dikeyde, içerik alt kaydırma çubuğunun altına inecektir.

Yeni basit çözüm: XIB'de: Üst, önden ve sondan süpervizyona ve yüksekliği 0'a ayarlanmış şekilde ana görünümünüzün üstüne yeni UIView ekleyin. Diğer alt görünümlere veya herhangi bir şeye bağlamanız gerekmez.

Eski çözüm:

Not: UIScrollView'ı yatay modda kullanıyorsanız, yatay girintileri yine de doğru şekilde ayarlamaz (başka bir hata mı?), Bu nedenle scrollView'ın başını / sonunu IB'deki safeAreaInsets'e sabitlemeniz gerekir.

Not 2: Aşağıdaki çözümde ayrıca tableView en alta kaydırılırsa ve denetleyiciye basıp geri açılırsa, artık altta olmayacak gibi bir sorun vardır.

override func viewDidLoad()
{
    super.viewDidLoad()

    // This parts gets rid of animation when pushing
    if #available(iOS 11, *)
    {
        self.tableView.contentInsetAdjustmentBehavior = .never
    }
}

override func viewDidDisappear(_ animated: Bool)
{
    super.viewDidDisappear(animated)
    // This parts gets rid of animation when popping
    if #available(iOS 11, *)
    {
        self.tableView.contentInsetAdjustmentBehavior = .never
    }
}

override func viewDidAppear(_ animated: Bool)
{
    super.viewDidAppear(animated)
    // This parts sets correct behaviour(insets are correct on iPhone X)
    if #available(iOS 11, *)
    {
        self.tableView.contentInsetAdjustmentBehavior = .automatic
    }
}

ParentView nedir?
PhoneyDeveloper

Görünüm denetleyicinizin ana görünümü, cevabı güncelledim. Teşekkürler.
El Horrible

UITableViewController'ı kullandığımda tableView, görünüm denetleyicisinin görünümüdür. Ayrıca, cihaz döndürüldüğünde ekler farklı olmalıdır. Ayarı istiyorum. TableView ilk göründüğünde animasyonu sevmiyorum.
PhoneyDeveloper

Sizin durumunuzda, UITableView denetleyicinin görünümü olduğundan, safeAreaInsets.bottom = 34 (portre) olmalıdır, böylece sadece tableView.contentInset = tableView.safeAreaInsets ayarlayabilirsiniz.
El Horrible

Bu benim için çalışmıyor. ViewDidLoad'da tüm girintiler sıfırdır. Bu kodu viewWillLayoutSubviews'te kullanmaya çalışırsam kaydırma göstergesi ekleniyor, ancak tableView'in kendisi yatay olarak kaydırabiliyor. ViewWillLayoutSubviews'te ayarlamayı devre dışı bırakmadan eklemelere bakarsam, alt ayarlananContentInset 21 olur ve görünen tek şey bu.
PhoneyDeveloper


2

lütfen yukarıdaki kodla birlikte ek kodu aşağıdaki gibi eklediğinizden emin olun. Sorunu çözdü

override func viewDidLayoutSubviews() { 
     super.viewDidLayoutSubviews() 
     tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) // print(thisUISBTV.adjustedContentInset) 
}

Bu tek başına sorunumu çözdü !! Teşekkür ederim. Bu konuda çok fazla saat boşa gitti!
Murat Yasar

2

Ayrıca sekme çubuğunu kullanırsanız, koleksiyon görünümünün alt içerik girişi sıfır olacaktır. Bunun için aşağıdaki kodu viewDidAppear'a koyun:

if #available(iOS 11, *) {
    tableView.contentInset = self.collectionView.safeAreaInsets
}

2

Benim durumumda bu işe yaradı (viewDidLoad'a koyun):

self.navigationController.navigationBar.translucent = YES;

1

collectionViewVeya üstündeki fazla boşluğu kaldırmaktableView

    if #available(iOS 11.0, *) {
        collectionView.contentInsetAdjustmentBehavior  = .never
        //tableView.contentInsetAdjustmentBehavior  = .never
    } else {
        automaticallyAdjustsScrollViewInsets = false
    }

Kodun üstünde collectionViewveya tableViewgezinme çubuğunun altına gider.
Aşağıdaki kod, koleksiyon görünümünün gezinme altına girmesini engelliyor

    self.edgesForExtendedLayout = UIRectEdge.bottom

ancak UICollectionView için aşağıdaki mantığı ve kodu kullanmayı seviyorum

Kenar girme değerleri, o dikdörtgenin temsil ettiği alanı küçültmek veya genişletmek için bir dikdörtgene uygulanır. Tipik olarak, görünüm mizanpajı sırasında görünümün çerçevesini değiştirmek için kenar girintileri kullanılır. Pozitif değerler, çerçevenin belirtilen miktarda eklenmesine (veya küçültülmesine) neden olur. Negatif değerler, çerçevenin belirtilen miktarda başlangıcına (veya genişletilmesine) neden olur.

collectionView.contentInset = UIEdgeInsets(top: -30, left: 0, bottom: 0, right: 0)
//tableView.contentInset = UIEdgeInsets(top: -30, left: 0, bottom: 0, right: 0)

UICollectionView için en iyi yol

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsets(top: -30, left: 0, bottom: 0, right: 0)
}

0

Bu kodu sil benim için çalış

self.edgesForExtendedLayout = UIRectEdgeNone

0
  if #available(iOS 11, *) {
        self.edgesForExtendedLayout = UIRectEdge.bottom
  }

Tablo görünümü olan özel resultsController ile UISearchController kullanıyordum. Sonuç denetleyicisine yeni denetleyiciye basmak, tablo görünümünün arama altına girmesine neden oldu.

Yukarıda listelenen kod sorunu tamamen çözdü

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.