Diyelim ki UIStackView'da görüntülenebilecek daha fazla görünüm ekledim, nasıl UIStackView
kaydırma yapabilirim ?
Diyelim ki UIStackView'da görüntülenebilecek daha fazla görünüm ekledim, nasıl UIStackView
kaydırma yapabilirim ?
Yanıtlar:
Durumda herkes çözüm arıyor kodu olmadan , ben Otomatik Düzen kullanarak, storyboard tamamen bunun için bir örnek oluşturdu.
Github'dan alabilirsiniz .
Temel olarak, örneği yeniden oluşturmak için (dikey kaydırma için):
UIScrollView
ve kısıtlamalarını ayarlayın.UIStackView
içinUIScrollView
Leading
, Trailing
, Top
& Bottom
gardarobu eşit olmalıdırUIScrollView
Width
arasındaki kısıtlamayı UIStackView
ve UIScrollView
.UIStackView
UIViews
içinUIStackView
Değişim Width
için Height
4. adımda, ve set Axis
= Horizontal
5. adımda, yatay UIStackView olsun.
Apple'ın Otomatik Mizanpaj Kılavuzu, Kaydırma Görünümleriyle Çalışma ile ilgili tüm bölümü içerir . İlgili bazı snippet'ler:
- İçerik görünümünün üst, alt, ön ve arka kenarlarını kaydırma görünümünün ilgili kenarlarına sabitleyin. İçerik görünümü artık kaydırma görünümünün içerik alanını tanımlar.
- (İsteğe bağlı) Yatay kaydırmayı devre dışı bırakmak için içerik görünümünün genişliğini kaydırma görünümünün genişliğine eşit olarak ayarlayın. İçerik görünümü artık kaydırma görünümünü yatay olarak dolduruyor.
- (İsteğe bağlı) Dikey kaydırmayı devre dışı bırakmak için içerik görünümünün yüksekliğini kaydırma görünümünün yüksekliğine eşit olarak ayarlayın. İçerik görünümü artık kaydırma görünümünü yatay olarak dolduruyor.
Ayrıca:
Düzeniniz, içerik görünümünün boyutunu tam olarak tanımlamalıdır (5. ve 6. adımlarda tanımlananlar hariç). … İçerik görünümü kaydırma görünümünden daha uzun olduğunda, kaydırma görünümü dikey kaydırmayı etkinleştirir. İçerik görünümü kaydırma görünümünden daha geniş olduğunda, kaydırma görünümü yatay kaydırmayı etkinleştirir.
Özetlemek gerekirse, kaydırma görünümünün içerik görünümü (bu durumda bir yığın görünümü) kenarlarına sabitlenmeli ve genişliği ve / veya yüksekliği aksi şekilde sınırlandırılmalıdır. Bu, yığın görünümünün içeriğinin, kaydırmanın istendiği yönde (doğrudan veya dolaylı olarak) sınırlandırılması gerektiği anlamına gelir; bu, örneğin dikey olarak kaydırılan yığın görünümündeki her görünüme bir yükseklik sınırlaması eklemek anlamına gelebilir. Aşağıda, yığın görünümü içeren kaydırma görünümünün dikey kaydırılmasına nasıl izin verileceğine bir örnek verilmektedir:
// Pin the edges of the stack view to the edges of the scroll view that contains it
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
// Set the width of the stack view to the width of the scroll view for vertical scrolling
stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
Need constraints for: Y position or height.
Bu hata yalnızca yığın görünümü için dikey kaydırmayı devre dışı bırakan hem genişlik hem de yükseklik kısıtlaması ayarlarsanız ortadan kalkar. Bu kod hala sizin için çalışıyor mu?
Burada en çok oylanan cevaptaki kısıtlamalar benim için çalıştı ve film şeridimde oluşturulduğu gibi aşağıdaki kısıtlamaların bir görüntüsünü yapıştırdım.
Diğerlerinin farkında olması gerekmesine rağmen iki konuya değindim:
Kabul edilen yanıttakine benzer kısıtlamalar ekledikten sonra kırmızı otomatik düzenleme hatası alırdım Need constraints for: X position or width
. Bu, yığın görünümünün alt görünümü olarak bir UILabel eklenerek çözülmüştür.
Alt görünümleri programlı olarak ekliyorum, bu yüzden aslında film şeridinde hiçbir alt görünümüm yoktu. Otomatik düzenleme hatalarından kurtulmak için film şeridine bir alt görünüm ekleyin, ardından gerçek alt görünümlerinizi ve kısıtlamalarınızı eklemeden önce yük altında kaldırın.
Başlangıçta UIButtons
UIStackView eklemek için çalıştı . Düğmeler ve görünümler yüklenir, ancak kaydırma görünümü kaydırılmaz . Bu, UILabels
düğmeler yerine Yığın Görünümü'ne eklenerek çözüldü . Aynı kısıtlamaları kullanarak, bu görünüm hiyerarşisi UILabels ile birlikte kayar, ancak UIButtonları kaydırılmaz.
UIButtons gibi bu sorundan karıştı mı (Stack Görüntüleme tarafından kullanılan) bir IntrinsicContentSize var gibi. Düğmelerin neden işe yaramadığını bilen biri varsa, nedenini bilmek isterim.
İşte referans için görünüm hiyerarşim ve kısıtlamalarım:
Eik diyor, şöyle UIStackView
ve UIScrollView
birlikte güzel oynamak, bkz burada .
Anahtar, UIStackView
farklı içerikler için değişken yükseklik / genişliğin UIScrollView
işlenmesidir ve daha sonra işini bu içeriği kaydırmak / sıçramaktan iyi yapar:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
scrollView.contentSize = CGSize(width: stackView.frame.width, height: stackView.frame.height)
}
Aynı şeyi yapmak istiyordum ve bu mükemmel gönderi üzerine tökezledi . Bunu çapa API'sını kullanarak programlı olarak yapmak istiyorsanız, işte bu yol.
Özetlemek gerekirse, gömmek UIStackView
Gözlerinde farklı UIScrollView
ve ankraj kısıtlamaları ayarlamak UIStackView
içine alacak şekilde UIScrollView
:
stackView.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor).active = true
stackView.trailingAnchor.constraintEqualToAnchor(scrollView.trailingAnchor).active = true
stackView.bottomAnchor.constraintEqualToAnchor(scrollView.bottomAnchor).active = true
stackView.topAnchor.constraintEqualToAnchor(scrollView.topAnchor).active = true
stackView.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true
Boş bir tam ekran sahnesine sahip olun
Kaydırma görünümü ekleyin. Kontrol görünümünü kaydırma görünümünden temel görünüme sürükleyin, sol-sağ-üst-alt, tümü sıfır ekleyin.
Kaydırma görünümüne yığın görünümü ekleyin. Yığın görünümünden kaydırma görünümüne Control-sürükleyin, sol-sağ-üst-alt, hepsi sıfır ekleyin.
Yığın görünümünün içine iki veya üç etiket yerleştirin.
Anlaşılır olması için etiketin arka plan rengini kırmızı yapın. Etiket yüksekliğini 100 olarak ayarlayın.
Şimdi her bir UILabel'in genişliğini ayarlayın :
Şaşırtıcı bir şekilde, yığın görünümünden değilUILabel
, kaydırma görünümüne kontrol sürükleyin ve eşit genişlikleri seçin .
Tekrarlamak için:
Bu kadar basit. Bu sır.
Gizli ipucu - Apple Bug:
Bu işe yaramaz tek öğe ile! Demoyu çalıştırmak için birkaç etiket ekleyin.
Sen bittin.
İpucu: Her yeni öğeye yükseklik eklemelisiniz . Herhangi bir kayan yığın görünümündeki her öğenin ya içsel bir boyutu (etiket gibi) olması ya da açık bir yükseklik kısıtlaması eklemesi gerekir.
Alternatif yaklaşım:
Yukarıda: Şaşırtıcı bir şekilde, UILabel'lerin genişliklerini kaydırma görünümünün genişliğine ayarlayın (yığın görünümü değil).
Alternatif ...
Yani iki seçeneğiniz var:
veya
Açık olmak gerekirse, bu yöntemlerden BİRİNİ yapın, her ikisini de YAPMAYIN.
Yatay kaydırma için. İlk olarak, a UIStackView
ve a oluşturun UIScrollView
ve bunları aşağıdaki şekilde görünümünüze ekleyin:
let scrollView = UIScrollView()
let stackView = UIStackView()
scrollView.addSubview(stackView)
view.addSubview(scrollView)
Ayarlamak için hatırlamak translatesAutoresizingMaskIntoConstraints
için false
üzerine UIStackView
ve UIScrollView
:
stackView.translatesAutoresizingMaskIntoConstraints = false
scrollView.translatesAutoresizingMaskIntoConstraints = false
Her şeyin çalışmasını sağlamak için, ön, üst ve alt ankrajların çapalara UIStackView
eşit olması gerekir UIScrollView
:
stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
Ancak, genişliğin çapası, çapanın genişliğine UIStackView
eşit veya daha büyük olmalıdır UIScrollView
:
stackView.widthAnchor.constraint(greaterThanOrEqualTo: scrollView.widthAnchor).isActive = true
Şimdi UIScrollView
, örneğin:
scrollView.heightAnchor.constraint(equalToConstant: 80).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo:view.safeAreaLayoutGuide.bottomAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo:view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo:view.trailingAnchor).isActive = true
Ardından, UIStackView
hizalama ve dağıtım için aşağıdaki ayarları denemenizi öneririz :
topicStackView.axis = .horizontal
topicStackView.distribution = .equalCentering
topicStackView.alignment = .center
topicStackView.spacing = 10
Son olarak addArrangedSubview:
, UIStackView'ınıza alt görünümler eklemek için yöntemi kullanmanız gerekir .
Yararlı bulabileceğiniz ek bir özellik, UIStackView
içinde tutulduğu için , UIScrollView
şimdi şeylerin biraz daha güzel görünmesini sağlamak için metin iç metinlerine erişebilmenizdir.
let inset:CGFloat = 20
scrollView.contentInset.left = inset
scrollView.contentInset.right = inset
// remember if you're using insets then reduce the width of your stack view to match
stackView.widthAnchor.constraint(greaterThanOrEqualTo: topicScrollView.widthAnchor, constant: -inset*2).isActive = true
Sadece şunu ekleyin viewdidload
:
let insets = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)
scrollVIew.contentInset = insets
scrollVIew.scrollIndicatorInsets = insets
ScrollableStackView'ı deneyebilirsiniz : https://github.com/gurhub/ScrollableStackView
Objective-C ve Swift uyumlu kütüphanedir. CocoaPods aracılığıyla edinilebilir .
Örnek Kod (Swift)
import ScrollableStackView
var scrollable = ScrollableStackView(frame: view.frame)
view.addSubview(scrollable)
// add your views with
let rectangle = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 55))
rectangle.backgroundColor = UIColor.blue
scrollable.stackView.addArrangedSubview(rectangle)
// ...
Örnek Kod (Amaç-C)
@import ScrollableStackView
ScrollableStackView *scrollable = [[ScrollableStackView alloc] initWithFrame:self.view.frame];
scrollable.stackView.distribution = UIStackViewDistributionFillProportionally;
scrollable.stackView.alignment = UIStackViewAlignmentCenter;
scrollable.stackView.axis = UILayoutConstraintAxisVertical;
[self.view addSubview:scrollable];
UIView *rectangle = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 55)];
[rectangle setBackgroundColor:[UIColor blueColor]];
// add your views with
[scrollable.stackView addArrangedSubview:rectangle];
// ...
Yığın Görünümü'nü kaydırma görünümünde dikey olarak ortalamak için bir kısıtlamanız varsa kaldırın.
Dikey yığın görünümü / kaydırma görünümü örneği (otomatik yerleşim EasyPeasy
için kullanarak ):
let scrollView = UIScrollView()
self.view.addSubview(scrollView)
scrollView <- [
Edges(),
Width().like(self.view)
]
let stackView = UIStackView(arrangedSubviews: yourSubviews)
stackView.axis = .vertical
stackView.distribution = .fill
stackView.spacing = 10
scrollView.addSubview(stackView)
stackView <- [
Edges(),
Width().like(self.view)
]
Alt görünümünüzün yüksekliğinin her birinin tanımlandığından emin olun!
İlk ve en önemlisi, görünümünüzü tercihen Sketch gibi bir şeyde tasarlayın veya kaydırılabilir bir içerik olarak ne istediğinize dair bir fikir edinin.
Bundan sonra görünüm denetleyicisini serbest hale getirin (nitelik denetçisinden seçin) ve görünümünüzün gerçek içerik boyutuna göre (boyut denetçisinden seçilecek) yükseklik ve genişliği ayarlayın.
Bundan sonra görünüm denetleyicisine bir kaydırma görünümü koydu ve bu, iOS'ta neredeyse her zaman çalıştığını bulduğum bir mantık (bir komut + tıklama ile elde edebileceğiniz bu görünüm sınıfının belgelerinden geçmeyi gerektirebilir. söz konusu sınıf veya googling yoluyla)
İki veya daha fazla görünümle çalışıyorsanız, önce daha önce tanıtılan veya daha ilkel olan bir görünümle başlayın ve daha sonra tanıtılan veya daha modern olan görünüme gidin. Dolayısıyla, burada kaydırma görünümü ilk kez sunulduğundan, önce kaydırma görünümü ile başlayın ve ardından yığın görünümüne gidin. Burada, kaydırma görünümü kısıtlamalarını süper görünümü karşısında her yöne sıfıra koyunuz. Tüm görünümlerinizi bu kaydırma görünümünün içine ve ardından yığın görünümüne yerleştirin.
Yığın görünümü ile çalışırken
Önce topraklama (alttan yukarıya yaklaşım) ile başlayın, yani, görünümünüzde etiketler, metin alanları ve görüntüler varsa, önce bu görünümleri (kaydırma görünümü içinde) düzenleyin ve ardından yığın görünümüne koyun.
Bundan sonra yığın görünümünün özelliğini değiştirin. İstenilen görünüm hala elde edilemiyorsa, başka bir yığın görünümü kullanın.
Görüşünüzü yaptıktan sonra, ana yığın görünümü ile kaydırma görünümü arasına bir kısıtlama getirirken, kısıtlamalı çocuklar ana yığın görünümü ile görünümü yığınlar. Umarım bu zamana kadar iyi çalışmalıdır ya da Xcode'dan önerilerde bulunarak bir uyarı alabilirsiniz, söylediklerini okuyun ve bunları uygulayın. Umarım şimdi beklentilerinize göre bir çalışma görünümü olması gerekir :).
İç içe veya tek Yığın görünümü için kaydırma görünümünde kök görünümüyle sabit bir genişlik ayarlanmalıdır. Kaydırma görünümünün içindeki ana yığın görünümü aynı genişliği ayarlamalıdır. [Kaydırma görünümüm bir Görünüm'ün altında yoksayılıyor
UIStackView ve UIScrollView arasında eşit bir Genişlik sınırlaması ayarlayın.
Herhangi biri yatay kaydırma görüntüsü arıyorsa
func createHorizontalStackViewsWithScroll() {
self.view.addSubview(stackScrollView)
stackScrollView.translatesAutoresizingMaskIntoConstraints = false
stackScrollView.heightAnchor.constraint(equalToConstant: 85).isActive = true
stackScrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
stackScrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
stackScrollView.bottomAnchor.constraint(equalTo: visualEffectViews.topAnchor).isActive = true
stackScrollView.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.topAnchor.constraint(equalTo: stackScrollView.topAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: stackScrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: stackScrollView.trailingAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: stackScrollView.bottomAnchor).isActive = true
stackView.heightAnchor.constraint(equalTo: stackScrollView.heightAnchor).isActive = true
stackView.distribution = .equalSpacing
stackView.spacing = 5
stackView.axis = .horizontal
stackView.alignment = .fill
for i in 0 ..< images.count {
let photoView = UIButton.init(frame: CGRect(x: 0, y: 0, width: 85, height: 85))
// set button image
photoView.translatesAutoresizingMaskIntoConstraints = false
photoView.heightAnchor.constraint(equalToConstant: photoView.frame.height).isActive = true
photoView.widthAnchor.constraint(equalToConstant: photoView.frame.width).isActive = true
stackView.addArrangedSubview(photoView)
}
stackView.setNeedsLayout()
}
Sahnenize bir kaydırma görünümü yerleştirin ve sahneyi dolduracak şekilde boyutlandırın. Ardından, kaydırma görünümünün içine yığın görünümü yerleştirin ve öğe ekle düğmesini yığın görünümünün içine yerleştirin. Her şey hazır olur olmaz aşağıdaki kısıtlamaları belirleyin:
Scroll View.Leading = Superview.LeadingMargin
Scroll View.Trailing = Superview.TrailingMargin
Scroll View.Top = Superview.TopMargin
Bottom Layout Guide.Top = Scroll View.Bottom + 20.0
Stack View.Leading = Scroll View.Leading
Stack View.Trailing = Scroll View.Trailing
Stack View.Top = Scroll View.Top
Stack View.Bottom = Scroll View.Bottom
Stack View.Width = Scroll View.Width
kod: Stack View.Width = Scroll View.Width
anahtardır.
MacOS Catalyst için yeni bir perspektif eklemek. MacOS uygulamaları pencerenin yeniden boyutlandırılmasını desteklediğinden, UIStackView
kaydırılamayan bir durumdan kaydırılabilir bir duruma geçmeniz veya tam tersi mümkündür. Burada iki ince şey var:
UIStackView
tüm alanlara uyacak şekilde tasarlanmıştır.UIScrollView
gezinme çubuğunuzun (veya macOS uygulamalarında araç çubuğunun) altındaki yeni kazanılan / kaybedilen alanı hesaba katmak için sınırlarını yeniden boyutlandırmaya çalışacaktır.Bu maalesef sonsuz bir döngü yaratacaktır. Ben UIScrollView
ve onun son derece aşina değilim adjustedContentInset
, ama benim layoutSubviews
yöntem benim günlüğünden , aşağıdaki davranış görüyorum:
UIScrollView
sınırlarını küçültmeye çalışır (çünkü araç çubuğunun altındaki alana gerek yoktur).UIStackView
izler.UIScrollView
tatmin edici değil ve daha büyük sınırlara geri dönmeye karar veriyor. Bu benim için çok garip geliyor çünkü kütükten gördüğüm şey bu UIScrollView.bounds.height == UIStackView.bounds.height
.UIStackView
izler.İki adımın sorunu çözeceği anlaşılıyor:
UIStackView.top
için UIScrollView.topMargin
.contentInsetAdjustmentBehavior
için .never
.Burada dikey olarak büyüyen dikey kaydırılabilir bir görünümle ilgileniyorum UIStackView
. Yatay bir çift için kodu uygun şekilde değiştirin.
Umarım gelecekte herkese yardımcı olur. İnternette bu söz kimse bulamadı ve ne olduğunu anlamak için bana oldukça uzun bir zaman mal oldu.