wake-up-neo.com

So legen Sie die Inhaltsgröße von UIScrollView dynamisch fest

Ich habe eine Frage zu UIScrollview.

Die Geschichte ist, ich habe eine UIView namens ChartsView, die ich selbst mit der Überschreibungsmethode drawRect() neu zeichnet. Der Inhalt der Zeichnung wurde dynamisch generiert. Also weiß ich nicht bis zur Laufzeit. Die Frage ist, wie und wo kann ich die Inhaltsgröße der Superansicht (ScrollView) dynamisch einstellen?

    - (void)viewDidLoad
    {
        [super viewDidLoad];

// not this way. it's fixed size.....
        ChartsView *chartsView = [[ChartsView alloc]initWithFrame:CGRectMake(0, 0, 320, 800)]; 

        self.scrollView.contentSize = chartsView.frame.size;

        [self.scrollView addSubview:chartsView];

    }
25
Roger Lee

Ein einfacher Weg

- (void)viewDidLoad
{
    float sizeOfContent = 0;
    UIView *lLast = [scrollView.subviews lastObject];
    NSInteger wd = lLast.frame.Origin.y;
    NSInteger ht = lLast.frame.size.height;

    sizeOfContent = wd+ht;

    scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, sizeOfContent);
}
58
IOS Rocks

Swift (2,0)

@IBOutlet weak var btnLatestButton: UIButton!

override func viewDidLoad() {
    super.viewDidLoad()

    let height = btnLatestButton.frame.size.height
    let pos = btnLatestButton.frame.Origin.y
    let sizeOfContent = height + pos + 10
    scrollview.contentSize.height = sizeOfContent

}

Oben ist natürlich, wenn Sie nur eine festgelegte Anzahl von Ansichten in Ihrem Scrollview haben. Die IOS Rocks-Methode ist zwar verfügbar, aber für mich nicht gut, da mehr Platz geschaffen wurde, als ich brauchte.

    let lastView : UIView! = scrollview.subviews.last
    let height = lastView.frame.size.height
    let pos = lastView.frame.Origin.y
    let sizeOfContent = height + pos + 10
    scrollview.contentSize.height = sizeOfContent
6
CularBytes

Es ist nicht 100% ig garantiert, dass das letzte Objekt im Array scrollView.subviews das höchste y-Origin-Objekt in Ihrer Bildlaufansicht zurückgibt. Das Subviews-Array ist nach Z-Index angeordnet (dh das letzte Objekt im Subviews-Array ist das Objekt, das am höchsten gestapelt ist und die oberste Subansicht in den Unteransichten der Bildlaufansicht ist.) Stattdessen ist die Verwendung einer einfachen Sortierfunktion genauer durchlaufen die Unteransichten und erhalten das Objekt mit dem höchsten y-Ursprung.

Hier ist eine grundlegende Funktion in Swift 3, die das kann: 

func calculateContentSize(scrollView: UIScrollView) -> CGSize {
    var topPoint = CGFloat()
    var height = CGFloat()

    for subview in scrollView.subviews {
        if subview.frame.Origin.y > topPoint {
            topPoint = subview.frame.Origin.y
            height = subview.frame.size.height
        }
    }
    return CGSize(width: scrollView.frame.size.width, height: height + topPoint)
}

Verwendung (in viewDidLayoutSubviews oder bei jeder Aktualisierung der Inhaltsgröße): 

scrollView.contentSize = calculateContentSize(scrollView: scrollView)

UPDATE Swift 4

Hier ist eine etwas konsistentere Version in Swift 4

extension UIScrollView {
    func updateContentView() {
        contentSize.height = subviews.sorted(by: { $0.frame.maxY < $1.frame.maxY }).last?.frame.maxY ?? contentSize.height
    }
}

Verwendungszweck:

myScrollView.updateContentView()
4

Vielen Dank an IOS Rocks und CularBytes für die Leads. Ich habe zwei Probleme (für mich) mit den obigen Lösungen gefunden:

  1. Ich habe immer einen UIView-Container als einziges Kind meiner UIScrollView. Daher musste ich die Art und Weise aktualisieren, wie ich die letzte Ansicht in diesem UIView-Kind nachschaue (siehe unten)
  2. Ich versetze meinen Inhalt in der UIScrollView und benötige als solche die absolute Position der letzten UIView (also relativ zum Fenster nicht zur übergeordneten Ansicht).

Außerdem verwende ich Autolayout, um die Seiten der UIScrollView zu fixieren, so dass ich mich nicht um die Breite kümmern muss (wie CularBytes).

Ich habe es mir ausgedacht und funktioniert (in Swift 3.0):

func setScrollViewContentSize() {

    var height: CGFloat
    let lastView = self.myScrollView.subviews[0].subviews.last!
    print(lastView.debugDescription) // should be what you expect

    let lastViewYPos = lastView.convert(lastView.frame.Origin, to: nil).y  // this is absolute positioning, not relative
    let lastViewHeight = lastView.frame.size.height

    // sanity check on these
    print(lastViewYPos)
    print(lastViewHeight)

    height = lastViewYPos + lastViewHeight

    print("setting scroll height: \(height)")

    myScrollView.contentSize.height = height
}

Ich nenne das in meiner viewDidAppear()-Methode.

3
the_dude_abides
override func viewDidAppear(_ animated: Bool) {
    var height: CGFloat
    let lastView = self.scrollView.subviews[0].subviews.last!

    let lastViewYPos = lastView.convert(lastView.frame.Origin, to: nil).y  
    let lastViewHeight = lastView.frame.size.height

    height = lastViewYPos + lastViewHeight
    scrollView.contentSize.height = height
}
1
Asad Jamil

Versuche dies - 

- (void)viewDidLoad
    {
        [super viewDidLoad];

// not this way. it's fixed size.....
        ChartsView *chartsView = [[ChartsView alloc]initWithFrame:CGRectMake(0, 0, 320, 800)]; 

        //self.scrollView.contentSize = chartsView.frame.size;
        [self.scrollView setContentSize:CGSizeMake(chartsView.frame.size.width, chartsView.frame.size.height)];
        [self.scrollView addSubview:chartsView];

    }
1
Abhishek Mishra

versuche dies 

- (void)viewDidLoad
        {
            [super viewDidLoad];

    // not this way. it's fixed size.....
            ChartsView *chartsView = [[ChartsView alloc]initWithFrame:CGRectMake(0, 0, 320, 800)]; 

            self.scrollView.contentSize = chartsView.frame.size;
            [self.scrollView setNeedsDisplay];
            [self.scrollView addSubview:chartsView];

    }
1
MrWaqasAhmed

Berechnen Sie UIScrollview contentSize dynamisch (abhängig vom Rahmen der Unteransichten)

Schnell:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    DispatchQueue.main.async {
        var contentRect = CGRect.zero

        for view in self.scrollView.subviews {
           contentRect = contentRect.union(view.frame)
        }

        self.scrollView.contentSize = contentRect.size
    }
}

Ziel c:

 - (void)viewDidLayoutSubviews {
     [super viewDidLayoutSubviews];

     dispatch_async(dispatch_get_main_queue(), ^ {
                        CGRect contentRect = CGRectZero;

                        for(UIView *view in scrollView.subviews)
                           contentRect = CGRectUnion(contentRect,view.frame);

                           scrollView.contentSize = contentRect.size;
                       });
}
0

Dies ist eine Erweiterung zu Swift 3

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 + 100)
        contentSize = newSize
    }
}
0
Bogdan Ustyak

Bei der Verwendung von Bildlaufansichten im Storyboard ist es besser, die Inhaltsgröße anhand der Anzahl der in der Bildlaufansicht vorhandenen Ansichten zu berechnen, als die Inhaltsgröße programmgesteuert mit einem statischen Wert anzugeben. Hier sind die Schritte zum dynamischen Abrufen der Inhaltsgröße.

Schritt 1: Fügen Sie eine Bildlaufansicht hinzu, um sie im Storyboard anzuzeigen, und fügen Sie führende, nachfolgende, obere und untere Einschränkungen hinzu (alle Werte sind Null).

Schritt 2: Fügen Sie nicht direkt Ansichten hinzu, die Sie für die direkte Bildlaufansicht benötigen. Fügen Sie zunächst eine Ansicht zur Bildlaufansicht hinzu (dies ist unsere Inhaltsansicht für alle Benutzeroberflächen Elemente). Fügen Sie dieser Ansicht die folgenden Einschränkungen hinzu. Führende, nachfolgende, obere und untere Randbedingungen (Alle Werte sind Null). Fügen Sie der Hauptansicht die gleiche Höhe und Breite hinzu (d. H. Die Bildlaufansicht enthält). Bei gleicher Höhe Priorität auf niedrig setzen. (Dies ist der wichtige Schritt zum Festlegen der Inhaltsgröße.) Die Höhe dieser Inhaltsansicht richtet sich nach der Anzahl der der Ansicht hinzugefügten Ansichten. Angenommen, Sie haben als letzte Ansicht eine Beschriftung hinzugefügt, und seine Y-Position ist 420, und die Höhe ist 20. Dann ist Ihre Inhaltsansicht 440.

Schritt 3: Fügen Sie Einschränkungen zu allen Ansichten hinzu, die Sie gemäß Ihren Anforderungen in der Inhaltsansicht hinzugefügt haben.

enter image description here

enter image description here

Ref: https://medium.com/@javedmultani16/uiscrollview-dynamic-content-size-through-storyboard-in-ios-fb873e9278e

0