可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I got question about UIScrollview
.
The story is I have a UIView
named ChartsView which I re-draw it myself by override method drawRect()
. The content of drawing was generated dynamically. So I do not know its size until runtime. The question is how/where can I set its super view's (scrollView) content size dynamically?Any idea about that?
- (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];
}
回答1:
One more easy way
- (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);
}
回答2:
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
}
Above ofcourse is when you just have a fixed amount of views on your scrollview.
IOS Rocks method is available but was not good for me, created more space then I needed.
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:
Thanks to IOS Rocks and CularBytes for the leads on this. I found two problems (for me) with the above solutions:
- I always have a container UIView as the only child of my UIScrollView, so I had to update the way I look up the last view in that child UIView (see below)
- I am offset'ing my content in the UIScrollView and as such needed to calculate the absolute position of that last UIView (so, relative to the window not the parent view)
Also I am using autolayout to pin the sides of the UIScrollView, so I don't need to worry about width (as is CularBytes).
Here's what I came up with and works (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
}
I call this in my viewDidAppear()
method.
回答4:
It is not 100% guaranteed that the last object in scrollView.subviews array will return the highest y-origin object in your scroll view. The subviews array is arranged by Z-Index (i.e the last object in the subviews array will be the object stacked the highest and will be the top-most subview in the scroll view's subviews. Instead it is more accurate to use a basic sort function to iterate through the subviews and get the object with the highest y-origin.
Here is a basic function in swift 3 that that can do so:
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)
}
Usage (in viewDidLayoutSubviews or whenever your content size updates):
scrollView.contentSize = calculateContentSize(scrollView: scrollView)
UPDATE SWIFT 4
Here is a more consise version in swift 4
extension UIScrollView {
func updateContentView() {
contentSize.height = subviews.sorted(by: { $0.frame.maxY < $1.frame.maxY }).last?.frame.maxY ?? contentSize.height
}
}
Usage:
myScrollView.updateContentView()
回答5:
try this
- (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];
}
回答6:
Try this -
- (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];
}
回答7:
This is an extension written on 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
}
}