Yanıtlar:
UIScrollView
A'nın içerik boyutunu , içerdiği alt görünümlere göre güncellemek için karşılaştığım en iyi yöntem :
Objective-C
CGRect contentRect = CGRectZero;
for (UIView *view in self.scrollView.subviews) {
contentRect = CGRectUnion(contentRect, view.frame);
}
self.scrollView.contentSize = contentRect.size;
hızlı
let contentRect: CGRect = scrollView.subviews.reduce(into: .zero) { rect, view in
rect = rect.union(view.frame)
}
scrollView.contentSize = contentRect.size
UIScrollView, içeriğinin yüksekliğini otomatik olarak bilmez. Yüksekliği ve genişliği kendiniz hesaplamalısınız
Gibi bir şeyle yap
CGFloat scrollViewHeight = 0.0f;
for (UIView* view in scrollView.subviews)
{
scrollViewHeight += view.frame.size.height;
}
[scrollView setContentSize:(CGSizeMake(320, scrollViewHeight))];
Ancak bu yalnızca görüşler birbirinin altındaysa işe yarar. Yan yana bir görünümünüz varsa, kaydırma çubuğunun içeriğini gerçekte olduğundan daha büyük ayarlamak istemiyorsanız, yalnızca birinin yüksekliğini eklemeniz gerekir.
int y = CGRectGetMaxY(((UIView*)[_scrollView.subviews lastObject]).frame); [_scrollView setContentSize:(CGSizeMake(CGRectGetWidth(_scrollView.frame), y))];
Set translatesAutoresizingMaskIntoConstraints
için NO
katılan tüm görünümlerde.
Kaydırma görünümünüzü, kaydırma görünümünün dışındaki kısıtlamalarla konumlandırın ve boyutlandırın.
Alt görünümleri kaydırma görünümünde düzenlemek için kısıtlamaları kullanın, kısıtlamaların kaydırma görünümünün dört kenarına da bağlı olduğundan ve boyutlarını almak için kaydırma görünümüne güvenmediğinden emin olun .
Kaynak: https://developer.apple.com/library/ios/technotes/tn2154/_index.html
Bunu Espuz ve KİK'in cevabına ekledim. Alt görünümlerin y konumunu kullanır ve kaydırma çubuklarını içermez. Düzenle Görünen en alt alt görünümün altını kullanır.
+ (CGFloat) bottomOfLowestContent:(UIView*) view
{
CGFloat lowestPoint = 0.0;
BOOL restoreHorizontal = NO;
BOOL restoreVertical = NO;
if ([view respondsToSelector:@selector(setShowsHorizontalScrollIndicator:)] && [view respondsToSelector:@selector(setShowsVerticalScrollIndicator:)])
{
if ([(UIScrollView*)view showsHorizontalScrollIndicator])
{
restoreHorizontal = YES;
[(UIScrollView*)view setShowsHorizontalScrollIndicator:NO];
}
if ([(UIScrollView*)view showsVerticalScrollIndicator])
{
restoreVertical = YES;
[(UIScrollView*)view setShowsVerticalScrollIndicator:NO];
}
}
for (UIView *subView in view.subviews)
{
if (!subView.hidden)
{
CGFloat maxY = CGRectGetMaxY(subView.frame);
if (maxY > lowestPoint)
{
lowestPoint = maxY;
}
}
}
if ([view respondsToSelector:@selector(setShowsHorizontalScrollIndicator:)] && [view respondsToSelector:@selector(setShowsVerticalScrollIndicator:)])
{
if (restoreHorizontal)
{
[(UIScrollView*)view setShowsHorizontalScrollIndicator:YES];
}
if (restoreVertical)
{
[(UIScrollView*)view setShowsVerticalScrollIndicator:YES];
}
}
return lowestPoint;
}
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.showsVerticalScrollIndicator = NO;
başında ve self.scrollView.showsHorizontalScrollIndicator = YES;
self.scrollView.showsVerticalScrollIndicator = YES;
sonunda neden yaptınız ?
İşte onu dönüştüremeyecek kadar tembel olan herkes için hızlı bir şekilde kabul edilen cevap :)
var contentRect = CGRectZero
for view in self.scrollView.subviews {
contentRect = CGRectUnion(contentRect, view.frame)
}
self.scrollView.contentSize = contentRect.size
İşte @ leviatan'ın cevabının Swift 3 uyarlaması:
UZANTI
import UIKit
extension UIScrollView {
func resizeScrollViewContentSize() {
var contentRect = CGRect.zero
for view in self.subviews {
contentRect = contentRect.union(view.frame)
}
self.contentSize = contentRect.size
}
}
KULLANIM
scrollView.resizeScrollViewContentSize()
Kullanımı çok kolay!
Aşağıdaki uzantı Swift'de yardımcı olacaktır .
extension UIScrollView{
func setContentViewSize(offset:CGFloat = 0.0) {
// dont show scroll indicators
showsHorizontalScrollIndicator = false
showsVerticalScrollIndicator = false
var maxHeight : CGFloat = 0
for view in subviews {
if view.isHidden {
continue
}
let newHeight = view.frame.origin.y + view.frame.height
if newHeight > maxHeight {
maxHeight = newHeight
}
}
// set content size
contentSize = CGSize(width: contentSize.width, height: maxHeight + offset)
// show scroll indicators
showsHorizontalScrollIndicator = true
showsVerticalScrollIndicator = true
}
}
Mantık, verilen cevaplarla aynıdır. Ancak, içindeki gizli görünümleri çıkarır UIScrollView
ve kaydırma göstergeleri gizlendikten sonra hesaplama gerçekleştirilir.
Ayrıca, isteğe bağlı bir işlev parametresi vardır ve parametreyi işleve ileterek bir ofset değeri ekleyebilirsiniz.
@Leviathan'dan harika ve en iyi çözüm. FP (fonksiyonel programlama) yaklaşımını kullanarak sadece hızlıya çevirmek.
self.scrollView.contentSize = self.scrollView.subviews.reduce(CGRect(), {
CGRectUnion($0, $1.frame)
}.size
self.contentSize = self.subviews.reduce(CGRect(), { $0.union($1.frame) }).size
Hangi çocuğun "daha ileri ulaştığını" hesaplayarak UIScrollView içindeki içeriğin yüksekliğini öğrenebilirsiniz. Bunu hesaplamak için, başlangıç noktası Y (başlangıç) ve ürün yüksekliğini hesaba katmalısınız.
float maxHeight = 0;
for (UIView *child in scrollView.subviews) {
float childHeight = child.frame.origin.y + child.frame.size.height;
//if child spans more than current maxHeight then make it a new maxHeight
if (childHeight > maxHeight)
maxHeight = childHeight;
}
//set content size
[scrollView setContentSize:(CGSizeMake(320, maxHeight))];
İşleri bu şekilde yaparak, öğelerin (alt görünümler) doğrudan birbirinin altına istiflenmesi gerekmez.
@ Emenegro çözümüne dayalı başka bir çözüm buldum
NSInteger maxY = 0;
for (UIView* subview in scrollView.subviews)
{
if (CGRectGetMaxY(subview.frame) > maxY)
{
maxY = CGRectGetMaxY(subview.frame);
}
}
maxY += 10;
[scrollView setContentSize:CGSizeMake(scrollView.frame.size.width, maxY)];
Temel olarak, görünümde hangi öğenin en aşağıda olduğunu buluruz ve alt kısma 10 piksellik bir dolgu ekleriz
Bir scrollView, başka scrollViews veya farklı inDepth subViews ağaçlarına sahip olabileceğinden, özyinelemeli derinlemesine çalıştırma tercih edilir.
Swift 2
extension UIScrollView {
//it will block the mainThread
func recalculateVerticalContentSize_synchronous () {
let unionCalculatedTotalRect = recursiveUnionInDepthFor(self)
self.contentSize = CGRectMake(0, 0, self.frame.width, unionCalculatedTotalRect.height).size;
}
private func recursiveUnionInDepthFor (view: UIView) -> CGRect {
var totalRect = CGRectZero
//calculate recursevly for every subView
for subView in view.subviews {
totalRect = CGRectUnion(totalRect, recursiveUnionInDepthFor(subView))
}
//return the totalCalculated for all in depth subViews.
return CGRectUnion(totalRect, view.frame)
}
}
kullanım
scrollView.recalculateVerticalContentSize_synchronous()
Veya sadece şunu yapın:
int y = CGRectGetMaxY(((UIView*)[_scrollView.subviews lastObject]).frame); [_scrollView setContentSize:(CGSizeMake(CGRectGetWidth(_scrollView.frame), y))];
(Bu çözüm benim tarafımdan bu sayfaya yorum olarak eklenmiştir. Bu yorum için 19 artı oy aldıktan sonra, bu çözümü topluluğun yararına resmi bir yanıt olarak eklemeye karar verdim!)
Swift4 için indirgeme kullanarak:
self.scrollView.contentSize = self.scrollView.subviews.reduce(CGRect.zero, {
return $0.union($1.frame)
}).size
Boyut, içine yüklenen içeriğe ve kırpma seçeneklerine bağlıdır. Bu bir metin görünümü ise, o zaman kaydırmaya, kaç satır metin, yazı tipi boyutuna vb. Bağlıdır. Kendinizi hesaplamanız neredeyse imkansız. İyi haber şu ki, görünüm yüklendikten sonra ve viewWillAppear'da hesaplanıyor. Ondan önce, hepsi bilinmiyor ve içerik boyutu çerçeve boyutuyla aynı olacak. Ancak, viewWillAppear yönteminde ve sonrasında (viewDidAppear gibi) içerik boyutu gerçek olacaktır.
Richy'nin kodunu sarma İçeriğin tamamen yeniden boyutlandırılmasını otomatikleştiren özel bir UIScrollView sınıfı yarattım!
SBScrollView.h
@interface SBScrollView : UIScrollView
@end
SBScrollView.m:
@implementation SBScrollView
- (void) layoutSubviews
{
CGFloat scrollViewHeight = 0.0f;
self.showsHorizontalScrollIndicator = NO;
self.showsVerticalScrollIndicator = NO;
for (UIView* view in self.subviews)
{
if (!view.hidden)
{
CGFloat y = view.frame.origin.y;
CGFloat h = view.frame.size.height;
if (y + h > scrollViewHeight)
{
scrollViewHeight = h + y;
}
}
}
self.showsHorizontalScrollIndicator = YES;
self.showsVerticalScrollIndicator = YES;
[self setContentSize:(CGSizeMake(self.frame.size.width, scrollViewHeight))];
}
@end
Nasıl kullanılır:
.h dosyasını görünüm denetleyicinize aktarın ve normal UIScrollView yerine bir SBScrollView örneği bildirin.
Dinamik içerik boyutunu şu şekilde ayarlayın.
self.scroll_view.contentSize = CGSizeMake(screen_width,CGRectGetMaxY(self.controlname.frame)+20);
Ayrıca Leviathan'ın en iyi sonuç veren cevabını buldum. Ancak tuhaf bir yükseklik hesaplıyordu. Alt görünümler arasında döngü oluştururken, kaydırma görünümü kaydırma göstergelerini gösterecek şekilde ayarlanmışsa, bunlar alt görünümler dizisinde olacaktır. Bu durumda çözüm, döngü oluşturmadan önce kaydırma göstergelerini geçici olarak devre dışı bırakmak ve ardından önceki görünürlük ayarını yeniden kurmaktır.
-(void)adjustContentSizeToFit
UIScrollView özel bir alt sınıfında genel bir yöntemdir.
-(void)awakeFromNib {
dispatch_async(dispatch_get_main_queue(), ^{
[self adjustContentSizeToFit];
});
}
-(void)adjustContentSizeToFit {
BOOL showsVerticalScrollIndicator = self.showsVerticalScrollIndicator;
BOOL showsHorizontalScrollIndicator = self.showsHorizontalScrollIndicator;
self.showsVerticalScrollIndicator = NO;
self.showsHorizontalScrollIndicator = NO;
CGRect contentRect = CGRectZero;
for (UIView *view in self.subviews) {
contentRect = CGRectUnion(contentRect, view.frame);
}
self.contentSize = contentRect.size;
self.showsVerticalScrollIndicator = showsVerticalScrollIndicator;
self.showsHorizontalScrollIndicator = showsHorizontalScrollIndicator;
}
Bunun UIScrollView içerik görüntüleme boyutunu güncellemenin düzgün bir yolu olabileceğini düşünüyorum.
extension UIScrollView {
func updateContentViewSize() {
var newHeight: CGFloat = 0
for view in subviews {
let ref = view.frame.origin.y + view.frame.height
if ref > newHeight {
newHeight = ref
}
}
let oldSize = contentSize
let newSize = CGSize(width: oldSize.width, height: newHeight + 20)
contentSize = newSize
}
}
import UIKit
class DynamicSizeScrollView: UIScrollView {
var maxHeight: CGFloat = UIScreen.main.bounds.size.height
var maxWidth: CGFloat = UIScreen.main.bounds.size.width
override func layoutSubviews() {
super.layoutSubviews()
if !__CGSizeEqualToSize(bounds.size,self.intrinsicContentSize){
self.invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
let height = min(contentSize.height, maxHeight)
let width = min(contentSize.height, maxWidth)
return CGSize(width: width, height: height)
}
}
viewDidLayoutSubviews
böylece otomatik düzen bitecekti, iOS7'de iyi çalıştı, ancak iOS6'da otomatik düzeni test etmek bir nedenden dolayı işi bitirmedi, bu yüzden bazı yanlış yükseklik değerlerine sahiptim, bu yüzdenviewDidAppear
şimdi iyi çalışıyor .. Belki birilerinin buna ihtiyacı olacağını belirtmek için. teşekkürler