如何使用 AutoLayout (iOS/Xamarin.iOS) 使 ScrollView 适合其内容?
How to make ScrollView fit its content using AutoLayout (iOS/Xamarin.iOS)?
目前我正在尝试使用 iOS 10.0
假设我有一个带有一个子视图的 ScrollView(该视图由其他三个视图组成)。
架构如下所示:
UIView
->ScrollView
-->View Container
--->TopView
--->MiddleView
--->BottomView
TopView 和 MiddleView 都有动态高度(根据内容可能会变小或变大)。
我相信我已经正确设置了约束(我一直在学习本教程 - https://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/)
问题本身是这样的:
BottomView 被截断(或者换句话说不想增长)。尽管显示了 BottomView 的内容 - 它显示在视图容器的边界下方。所以不可能看到 BottomView 的所有子视图和控件('因为滚动视图的弹跳效果起作用)
有什么建议或问题出在哪里吗?
关于布局功能,用Frame比较清楚,我按照你的描述写了个例子:
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;
}
}
}
您可以更改参数以获得您想要的,这是我 GitHub:
中的完整解决方案
有需要的可以看看。希望对你有帮助。
已解决
以下方法成功了:
我已将我的 ScrollView 放在一个视图中,所以现在层次结构如下所示(见图)
我唯一需要做的就是弄清楚如何正确处理在从 MiddleView 和 TopView 隐藏一些视图后仍然存在的额外 space(将这些视图高度约束常量值设置为 0 是不够的一些理由..)。但这完全超出了我的问题范围:)
编辑:
对于那些想知道如何使用我上面描述的附加 space 解决问题的人,这里是帮助我解决问题的 link - solution
目前我正在尝试使用 iOS 10.0
假设我有一个带有一个子视图的 ScrollView(该视图由其他三个视图组成)。 架构如下所示:
UIView
->ScrollView
-->View Container
--->TopView
--->MiddleView
--->BottomView
TopView 和 MiddleView 都有动态高度(根据内容可能会变小或变大)。
我相信我已经正确设置了约束(我一直在学习本教程 - https://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/)
问题本身是这样的: BottomView 被截断(或者换句话说不想增长)。尽管显示了 BottomView 的内容 - 它显示在视图容器的边界下方。所以不可能看到 BottomView 的所有子视图和控件('因为滚动视图的弹跳效果起作用)
有什么建议或问题出在哪里吗?
关于布局功能,用Frame比较清楚,我按照你的描述写了个例子:
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;
}
}
}
您可以更改参数以获得您想要的,这是我 GitHub:
中的完整解决方案有需要的可以看看。希望对你有帮助。
已解决
以下方法成功了: 我已将我的 ScrollView 放在一个视图中,所以现在层次结构如下所示(见图)
我唯一需要做的就是弄清楚如何正确处理在从 MiddleView 和 TopView 隐藏一些视图后仍然存在的额外 space(将这些视图高度约束常量值设置为 0 是不够的一些理由..)。但这完全超出了我的问题范围:)
编辑:
对于那些想知道如何使用我上面描述的附加 space 解决问题的人,这里是帮助我解决问题的 link - solution