iOS:setContentSize 导致我的整个 UIScrollView 框架跳跃
Posted
技术标签:
【中文标题】iOS:setContentSize 导致我的整个 UIScrollView 框架跳跃【英文标题】:iOS: setContentSize is causing my entire UIScrollView frame to jump 【发布时间】:2013-05-31 20:00:10 【问题描述】:对于这个问题,我可能缺少一个简单的解决方案,但我似乎找不到原因。
问题: 每次我在滚动视图上调用 setContentSize 时,都会导致整个滚动视图框架发生移动。
问题:为什么每次调用 setContentSize 时它的位置都会重置?以及如何让它停止?
注意事项:
Scrollview 中的 contentOffSet 没问题。这是整个 跳转到其原始位置的滚动视图框架。 滚动视图旨在通过按下按钮上下移动,显示下方的 UIView。 -- 这很好用,但是当打开一个单元格并且 CollapseClick 对其自身(滚动视图)调用 setContentSize 时,整个滚动视图会过早地跳回 任何建议都将不胜感激。谢谢。布局:
简单布局:1 个滚动视图(全屏),1 个 UIView 容器(高度:120 点)随着滚动视图上下移动而出现和消失。MasterView.m(部分)
-(void)showPostShout
CGRect newCCFrame = myCollapseClick.frame;//<----myCollapseClick is the UIScrollView
if (!postShoutOpen)
newCCFrame.origin.y += 120;
[UIView animateWithDuration:.4 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^
self.postShoutContainer.alpha = 1;
myCollapseClick.frame= newCCFrame;
completion: ^(BOOL finished)
NSLog(@"finished!");
];
else
newCCFrame.origin.y -= 120;
[UIView animateWithDuration:.3 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^
self.postShoutContainer.alpha = 0;
myCollapseClick.frame= newCCFrame;
completion: ^(BOOL finished)
NSLog(@"finished2!");
];
postShoutOpen = !postShoutOpen;
CollapseableClick.m(违规部分?)
-(void)repositionCollapseClickCellsBelowIndex:(int)index withOffset:(float)offset
for (int yy = index+1; yy < self.dataArray.count; yy++)
CollapseClickCell *cell = [self.dataArray objectAtIndex:yy];
cell.frame = CGRectMake(cell.frame.origin.x, cell.frame.origin.y + offset, cell.frame.size.width, cell.frame.size.height);
// Resize self.ContentSize
CollapseClickCell *lastCell = [self.dataArray objectAtIndex:self.dataArray.count - 1];
[self setContentSize:CGSizeMake(self.frame.size.width, lastCell.frame.origin.y + lastCell.frame.size.height + kCCPad)];
collapseableclick.m(整体)
//
// CollapseClick.m
// CollapseClick
//
// Created by Ben Gordon on 2/28/13.
// Copyright (c) 2013 Ben Gordon. All rights reserved.
//
#import "CollapseClick.h"
//#import "UIScrollView+SVPullToRefresh.h"
@implementation CollapseClick
@synthesize CollapseClickDelegate;
- (id)initWithFrame:(CGRect)frame
self = [super initWithFrame:frame];
if (self)
// Initialization code
self.isClickedArray = [[NSMutableArray alloc] initWithCapacity:[CollapseClickDelegate numberOfCellsForCollapseClick]];
self.dataArray = [[NSMutableArray alloc] initWithCapacity:[CollapseClickDelegate numberOfCellsForCollapseClick]];
[self reloadCollapseClick];
return self;
#pragma mark - Load Data
-(void)reloadCollapseClick
// Set Up: Height
float totalHeight = 0;
// If Arrays aren't Init'd, Init them
if (!(self.isClickedArray))
self.isClickedArray = [[NSMutableArray alloc] initWithCapacity:[CollapseClickDelegate numberOfCellsForCollapseClick]];
if (!(self.dataArray))
self.dataArray = [[NSMutableArray alloc] initWithCapacity:[CollapseClickDelegate numberOfCellsForCollapseClick]];
// Make sure they are clear
[self.isClickedArray removeAllObjects];
[self.dataArray removeAllObjects];
// Remove all subviews
for (UIView *subview in self.subviews)
[subview removeFromSuperview];
// Add cells
for (int xx = 0; xx < [CollapseClickDelegate numberOfCellsForCollapseClick]; xx++)
// Create Cell
///add delegate methods for agree/disagree debaters here
CollapseClickCell *cell = [CollapseClickCell newCollapseClickCellWithTitle:[CollapseClickDelegate titleForCollapseClickAtIndex:xx] stats:[CollapseClickDelegate statsForCollapseClick:xx] index:xx content:[CollapseClickDelegate viewForCollapseClickContentViewAtIndex:xx]];
// Set cell.TitleView's backgroundColor
if ([(id)CollapseClickDelegate respondsToSelector:@selector(colorForCollapseClickTitleViewAtIndex:)])
cell.TitleView.backgroundColor = [CollapseClickDelegate colorForCollapseClickTitleViewAtIndex:xx];
else
cell.TitleView.backgroundColor = [UIColor colorWithWhite:0.4 alpha:1.0];
// Set cell.TitleLabel's Color
if ([(id)CollapseClickDelegate respondsToSelector:@selector(colorForTitleLabelAtIndex:)])
cell.TitleLabel.textColor = [CollapseClickDelegate colorForTitleLabelAtIndex:xx];
else
cell.TitleLabel.textColor = [UIColor whiteColor];
// Set cell.TitleArrow's Color
if ([(id)CollapseClickDelegate respondsToSelector:@selector(colorForTitleArrowAtIndex:)])
[cell.TitleArrow drawWithColor:[CollapseClickDelegate colorForTitleArrowAtIndex:xx]];
else
[cell.TitleArrow drawWithColor:[UIColor colorWithWhite:0.0 alpha:0.35]];
// Set cell.ContentView's size
cell.ContentView.frame = CGRectMake(0, kCCHeaderHeight + kCCPad, self.frame.size.width, cell.ContentView.frame.size.height);
// Set cell's size
cell.frame = CGRectMake(0, totalHeight, self.frame.size.width, kCCHeaderHeight);
// Add target to Button
[cell.TitleButton addTarget:self action:@selector(didSelectCollapseClickButton:) forControlEvents:UIControlEventTouchUpInside];
// Add cell
[self addSubview:cell];
// Add to DataArray & isClickedArray
[self.isClickedArray addObject:[NSNumber numberWithBool:NO]];
[self.dataArray addObject:cell];
// Calculate totalHeight
totalHeight += kCCHeaderHeight + kCCPad;
// Set self's ContentSize and ContentOffset
[self setContentSize:CGSizeMake(self.frame.size.width, totalHeight)];
[self setContentOffset:CGPointZero];
[[NSNotificationCenter defaultCenter] postNotificationName:@"CollapseClickUpdated" object: self ];
#pragma mark - Reposition Cells
-(void)repositionCollapseClickCellsBelowIndex:(int)index withOffset:(float)offset
for (int yy = index+1; yy < self.dataArray.count; yy++)
CollapseClickCell *cell = [self.dataArray objectAtIndex:yy];
cell.frame = CGRectMake(cell.frame.origin.x, cell.frame.origin.y + offset, cell.frame.size.width, cell.frame.size.height);
// Resize self.ContentSize
CollapseClickCell *lastCell = [self.dataArray objectAtIndex:self.dataArray.count - 1];
[self setContentSize:CGSizeMake(self.frame.size.width, lastCell.frame.origin.y + lastCell.frame.size.height + kCCPad)];
#pragma mark - Did Click
-(void)didSelectCollapseClickButton:(UIButton *)titleButton
BOOL isOpen = NO;
// Cell is OPEN -> CLOSED
if ([[self.isClickedArray objectAtIndex:titleButton.tag] boolValue] == YES)
[self closeCollapseClickCellAtIndex:titleButton.tag animated:YES];
// Cell is CLOSED -> OPEN
else
[self openCollapseClickCellAtIndex:titleButton.tag animated:YES];
isOpen = YES;
// Call delegate method
if ([(id)CollapseClickDelegate respondsToSelector:@selector(didClickCollapseClickCellAtIndex:isNowOpen:)])
[CollapseClickDelegate didClickCollapseClickCellAtIndex:titleButton.tag isNowOpen:isOpen];
#pragma mark - Open CollapseClickCell
-(void)openCollapseClickCellAtIndex:(int)index animated:(BOOL)animated
// Check if it's not open first
if ([[self.isClickedArray objectAtIndex:index] boolValue] != YES)
float duration = 0;
if (animated)
duration = 0.25;
[UIView animateWithDuration:duration animations:^
// Resize Cell
CollapseClickCell *cell = [self.dataArray objectAtIndex:index];
cell.frame = CGRectMake(cell.frame.origin.x, cell.frame.origin.y, cell.frame.size.width, cell.ContentView.frame.origin.y + cell.ContentView.frame.size.height + kCCPad);
// Change Arrow orientation
CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI/2);
cell.TitleArrow.transform = transform;
// Change isClickedArray
[self.isClickedArray replaceObjectAtIndex:index withObject:[NSNumber numberWithBool:YES]];
// Reposition all CollapseClickCells below Cell
[self repositionCollapseClickCellsBelowIndex:index withOffset:cell.ContentView.frame.size.height + kCCPad];
];
-(void)openCollapseClickCellsWithIndexes:(NSArray *)indexArray animated:(BOOL)animated
// This works off of NSNumbers for each Index
for (int ii = 0; ii < indexArray.count; ii++)
id indexID = indexArray[ii];
if ([indexID isKindOfClass:[NSNumber class]])
[self openCollapseClickCellAtIndex:[indexID intValue] animated:animated];
#pragma mark - Close CollapseClickCell
-(void)closeCollapseClickCellAtIndex:(int)index animated:(BOOL)animated
// Check if it's open first
if ([[self.isClickedArray objectAtIndex:index] boolValue] == YES)
float duration = 0;
if (animated)
duration = 0.25;
[UIView animateWithDuration:duration animations:^
// Resize Cell
CollapseClickCell *cell = [self.dataArray objectAtIndex:index];
cell.frame = CGRectMake(cell.frame.origin.x, cell.frame.origin.y, cell.frame.size.width, kCCHeaderHeight);
// Change Arrow orientation
CGAffineTransform transform = CGAffineTransformMakeRotation(0);
cell.TitleArrow.transform = transform;
// Change isClickedArray
[self.isClickedArray replaceObjectAtIndex:index withObject:[NSNumber numberWithBool:NO]];
// Reposition all CollapseClickCells below Cell
[self repositionCollapseClickCellsBelowIndex:index withOffset:-1*(cell.ContentView.frame.size.height + kCCPad)];
];
-(void)closeCollapseClickCellsWithIndexes:(NSArray *)indexArray animated:(BOOL)animated
// This works off of NSNumbers for each Index
for (int ii = 0; ii < indexArray.count; ii++)
id indexID = indexArray[ii];
if ([indexID isKindOfClass:[NSNumber class]])
[self closeCollapseClickCellAtIndex:[indexID intValue] animated:animated];
#pragma mark - CollapseClickCell for Index
-(CollapseClickCell *)collapseClickCellForIndex:(int)index
if ([[self.dataArray objectAtIndex:index] isKindOfClass:[CollapseClickCell class]])
return [self.dataArray objectAtIndex:index];
return nil;
#pragma mark - Scroll To Cell
-(void)scrollToCollapseClickCellAtIndex:(int)index animated:(BOOL)animated
CollapseClickCell *cell = [self.dataArray objectAtIndex:index];
[self setContentOffset:CGPointMake(cell.frame.origin.x, cell.frame.origin.y) animated:animated];
#pragma mark - Content View for Cell
-(UIView *)contentViewForCellAtIndex:(int)index
CollapseClickCell *cell = [self.subviews objectAtIndex:index];
return cell.ContentView;
@end
【问题讨论】:
【参考方案1】:有一个简单的解决方案:关闭自动布局。
对我来说,我并没有为我的整个故事板关闭它,只是我加载了一个笔尖。(打算用作整个网站的小部件。)问题解决了。
WWDC 2012 视频“Session 228 - Best Practices for Mastering Auto Layout”解释并解决了这个问题,从 30 分 45 秒开始。
【讨论】:
以上是关于iOS:setContentSize 导致我的整个 UIScrollView 框架跳跃的主要内容,如果未能解决你的问题,请参考以下文章
iOS ScrollView setContentSize 不起作用
UIScrollView setContentSize 使用自动布局打破视图
UITextView setContentSize 不起作用?
使用 UIScrollView 和 setContentSize 时设置正确的大小