我对UIScrollview
提出了疑问。
故事是我有一个名为ChartsView的UIView
我自己通过覆盖方法drawRect()
重新绘制它。绘图的内容是动态生成的。所以直到运行时我才知道它的大小。问题是如何/在哪里可以动态设置其超级视图(scrollView)的内容大小?有什么想法吗?
- (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];
}
答案 0 :(得分:58)
一个更简单的方法
- (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);
}
答案 1 :(得分:10)
不能100%保证scrollView.subviews数组中的最后一个对象将返回滚动视图中最高的y-origin对象。子视图数组由Z-Index排列(即子视图数组中的最后一个对象将是堆叠最高的对象,并且将成为滚动视图子视图中的最顶层子视图。相反,它更准确地使用一个基本的排序函数,用于遍历子视图并获取具有最高y源的对象。
这是swift 3中的一个基本功能,可以这样做:
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)
}
用法(在viewDidLayoutSubviews或内容大小更新时):
scrollView.contentSize = calculateContentSize(scrollView: scrollView)
UPDATE SWIFT 4
这是swift 4中更加简洁的版本
extension UIScrollView {
func updateContentView() {
contentSize.height = subviews.sorted(by: { $0.frame.maxY < $1.frame.maxY }).last?.frame.maxY ?? contentSize.height
}
}
用法:
myScrollView.updateContentView()
答案 2 :(得分:6)
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
}
当然,您可以在滚动视图中获得固定数量的观看次数。 IOS Rocks方法可用但对我不好,创造了更多空间,然后我需要。
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
答案 3 :(得分:3)
感谢IOS Rocks和CularBytes对此的引导。我发现上述解决方案存在两个问题(对我而言):
另外我使用autolayout来固定UIScrollView的两侧,所以我不需要担心宽度(就像CularBytes一样)。
这是我想出的并且有效(在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
}
我在viewDidAppear()
方法中调用此方法。
答案 4 :(得分:1)
试试这个
- (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];
}
答案 5 :(得分:1)
试试这个 -
- (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];
}
答案 6 :(得分:1)
在情节提要中使用滚动视图时,最好根据滚动视图中显示的视图数来计算内容大小,而不是通过编程将内容大小设置为静态值。 这是动态获取内容大小的步骤。
第1步: 添加Scrollview以在情节提要中查看,并添加开头,结尾,顶部和底部约束(所有值为零)。
第2步: 不要在直接滚动视图中直接添加所需的视图,首先要在滚动视图中添加一个视图(这将是我们所有UI元素的内容视图)。在此视图中添加以下约束。 前导,尾随,顶部和底部约束(所有值均为零)。 在主视图(即包含滚动视图)中添加相等的高度,相等的宽度。对于相等的高度,将优先级设置为低。 (这是设置内容大小的重要步骤)。 此内容视图的高度将根据添加到该视图的视图数确定。假设您添加的最后一个视图是一个标签,并且其Y位置是420,高度是20,那么您的内容视图将是440。
第3步::根据需要向在内容视图中添加的所有视图添加约束。
答案 7 :(得分:1)
SWIFT 5
您还可以通过调整 UIScrollView
以编程方式更新 UIScrollView.contentLayoutGuide
的 contentView,以下是将 contentview 限制为 yourView
高度的示例:
self.scrollView.translatesAutoresizingMaskIntoConstraints = false
self.scrollView.translatesAutoresizingMaskIntoConstraints = false
self.scrollView.heightAnchor.constraint(equalTo: self.view.heightAnchor).isActive = true
self.scrollView.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true
self.scrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
self.scrollView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
self.scrollView.contentLayoutGuide.heightAnchor.constraint(equalTo: yourView.heightAnchor, multiplier: 1).isActive = true
self.scrollView.contentLayoutGuide.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 1).isActive = true
self.scrollView.contentLayoutGuide.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
self.scrollView.contentLayoutGuide.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
答案 8 :(得分:0)
这是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
}
}
答案 9 :(得分:0)
动态计算UIScrollview contentSize(取决于子视图框架)
迅速:
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
}
}
目标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;
});
}
答案 10 :(得分:0)
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
}
答案 11 :(得分:0)