1

Currently I am trying to do this using iOS 10.0

Lets say I have a ScrollView with one child subview (which is a view that consists of three other views). Schema looks like this:

UIView
->ScrollView
-->View Container
--->TopView
--->MiddleView
--->BottomView 

Both TopView and MiddleView have dynamic height (it may be smaller or bigger depending on content).

I believe that I have set constraints properly (I have been following this tutorial - https://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/)

Here is my view heirarchy

The problem itself looks like this: the BottomView gets truncated (or in other words doesn't want to grow). Though the content of BottomView is displayed - it is displayed below View Container's bounds. So it is impossible to see all subviews and controls of BottomView ('cause bounce effect of scroll view comes into play)

Any suggestions what is going on or where the problem might be ?

  • "it is displayed below View Container's bounds": If i understand correct your "View Container is not expanding it's height"? Next Problem: Thus scroll view will not increase/calculate right content size? – maddy Sep 27 '16 at 07:47
  • it looks more like 'ViewContainer' will not calculate right contents size Also, when TopView and MiddleView have small content height there is 'blank' space below all views – Oleksandr Brusylo Sep 27 '16 at 11:54

2 Answers2

0

About the layout function, using Frame is more clear, I wrote a sample according to your description:

using System;
using UIKit;
using CoreGraphics;

namespace LayoutSample
{
    public class MainViewController : UIViewController
    {
        private MainView mainView;

        public override void LoadView()
        {
            mainView = new MainView();
            this.View = mainView;
        }

        public override void ViewDidLoad()
        {
            //If you don't know what is this code meaning, try to comment it, then you will get what it is.
            this.AutomaticallyAdjustsScrollViewInsets = false;

            UIBarButtonItem left0 = new UIBarButtonItem("-Frame", UIBarButtonItemStyle.Done, delegate
            {
                mainView.DecreaseScrollViewFrame();
            });

            UIBarButtonItem left1 = new UIBarButtonItem("-CS", UIBarButtonItemStyle.Done, delegate
            {
                mainView.DecreaseScrollViewContentSize();
            });

            UIBarButtonItem right0 = new UIBarButtonItem("+Frame", UIBarButtonItemStyle.Done, delegate
            {
                mainView.IncreaseScrollViewFrame();
            });

            UIBarButtonItem right1 = new UIBarButtonItem("+CS", UIBarButtonItemStyle.Done, delegate
            {
                mainView.IncreaseScrollViewContentSize();
            });

            this.NavigationItem.SetLeftBarButtonItems(new UIBarButtonItem[] { left0,left1 }, true);

            this.NavigationItem.SetRightBarButtonItems(new UIBarButtonItem[] { right0, right1 }, true);

        }
    }

    class MainView : UIView
    {
        private UIScrollView scrollView;
        private UIView containerView;
        private UIView topView;
        private UIView midView;
        private UIView bottomView;

        public MainView()
        {
            scrollView = new UIScrollView();
            scrollView.BackgroundColor = UIColor.Red;
            nfloat navigationBarHeight = 64;
            scrollView.Frame = new CGRect(0, navigationBarHeight, UIScreen.MainScreen.Bounds.Width, UIScreen.MainScreen.Bounds.Height - 100 - navigationBarHeight);
            scrollView.ContentSize = scrollView.Frame.Size;
            this.AddSubview(scrollView);

            containerView = new UIView();
            containerView.BackgroundColor = UIColor.Green;
            scrollView.AddSubview(containerView);

            topView = new UIView();
            topView.BackgroundColor = UIColor.Blue;
            containerView.AddSubview(topView);

            midView = new UIView();
            midView.BackgroundColor = UIColor.Purple;
            containerView.AddSubview(midView);

            bottomView = new UIView();
            bottomView.BackgroundColor = UIColor.Yellow;
            containerView.AddSubview(bottomView);
        }

        //It will also be invoked when your view's Frame is changed, and of cause you can invoke it whenever you want
        public override void LayoutSubviews()
        {
            Console.WriteLine("LayoutSubviews");

            nfloat padding = 10;

            CGRect containerFrame = new CGRect(new CGPoint(0,0),scrollView.ContentSize);
            containerFrame.X += padding;
            containerFrame.Y += padding;
            containerFrame.Width -= 2 * padding;
            containerFrame.Height -= 2 * padding;
            containerView.Frame = containerFrame;

            nfloat bottomHeight = 100;
            nfloat topHeight = 0.3f * containerView.Frame.Height;
            nfloat midHeight = containerView.Frame.Height - topHeight - bottomHeight - 4 * padding;

            nfloat containerSubviewWidth = containerView.Frame.Width - 2 * padding;
            topView.Frame = new CGRect(padding, padding, containerSubviewWidth, topHeight);
            midView.Frame = new CGRect(padding, padding + topView.Frame.Y + topView.Frame.Height, containerSubviewWidth, midHeight);
            bottomView.Frame = new CGRect(padding, padding + midView.Frame.Y + midView.Frame.Height, containerSubviewWidth, bottomHeight);
        }

        public void IncreaseScrollViewContentSize()
        {
            CGSize tmpSize = scrollView.ContentSize;
            tmpSize.Height += 100;
            scrollView.ContentSize = tmpSize;
            LayoutSubviews();
        }

        public void DecreaseScrollViewContentSize()
        {
            CGSize tmpSize = scrollView.ContentSize;
            tmpSize.Height -= 100;
            scrollView.ContentSize = tmpSize;
            LayoutSubviews();
        }

        public void IncreaseScrollViewFrame()
        {
            CGRect tmpRect = scrollView.Frame;
            tmpRect.Height += 10;
            scrollView.ContentSize = new CGSize(tmpRect.Width, tmpRect.Height);
            scrollView.Frame = tmpRect;
        }

        public void DecreaseScrollViewFrame()
        {
            CGRect tmpRect = scrollView.Frame;
            tmpRect.Height -= 10;
            scrollView.ContentSize = new CGSize(tmpRect.Width, tmpRect.Height);
            scrollView.Frame = tmpRect;
        }
    }
}

You can change the parameter to get what exactly you want, and this is the complete solution in my GitHub:

lwnwowone/LayoutSample

Take a look if you need. Hope it can help you.

Alanc Liu
  • 1,294
  • 10
  • 15
  • Thank you for provided code, but I am afraid that this not what I am looking for. I mean, I do use autolayout. It should resolve any constraint changes, shouldn't it ? I believe there is much simpler and elegant solution with no code involved - pure 'xCode designer constraints solution' I would say. But anyway thank you for your work! – Oleksandr Brusylo Sep 27 '16 at 07:15
  • Yeah, there must have a way to finish by just using graphic designer, but it's more hard to discuss when you meet some problem with it, because it's very hard to explain unless you can share the whole solution. And if you have some collaborators and you want to use like Git/SVN to manage your project, you will get so many merge issues. So I suggest you try my code, it's very easy. If you still want to use the designer, you should share your solution somewhere, then me or someone may can help you. – Alanc Liu Sep 27 '16 at 09:08
0

Solved

The following did the trick: I have put my ScrollView in a View so now hierarchy looks like this (see image)

Updated view hierarchy

The only thing that I need to do is figure out how to properly handle additional space that remains after hiding some views from MiddleView and TopView (setting those views height constraints constant value to 0 is not enough for some reason..). But this is quite out of scope of my question :)

EDIT:

For those who wants to know how to fix the problem with additional space I described above, here is the link that helped me to solve it - solution

Dilip Tiwari
  • 1,441
  • 18
  • 31