gpt4 book ai didi

iphone - 如何实现具有 1000+ 个 subview 的 UIScrollView?

转载 作者:太空狗 更新时间:2023-10-30 03:21:26 26 4
gpt4 key购买 nike

我正在努力编写一个应用程序的一部分,它应该像 native iphone 照片应用程序一样运行。查看了 Orielly 的 iphone sdk app development book,它给出了一个示例代码来实现这个所谓的页面闪烁。那里的代码首先创建所有 subview ,然后隐藏/取消隐藏它们。在给定的时间只有 3 个 subview 是可见的,其余的是隐藏的。经过大量努力,我让它与当时只有大约 15 页的应用程序一起使用。

当我添加 300 页后,很明显这种预分配如此多 subview 的方法存在性能/内存问题。然后我想可能是为了我的情况我应该只分配 3 个 subview 而不是隐藏/取消隐藏它们。可能我应该在运行时删除/添加 subview 。但无法弄清楚 UIScrollView 是否可以动态更新内容。例如,开始时有 3 个帧位于屏幕的不同 x 偏移量(0、320、640),如 UIScrollView 所理解的那样。一旦用户移动到第 3 页,我如何确保我能够添加第 4 页并删除第 1 页,而 UIScrollView 不会混淆?

希望有解决此类问题的标准方法...有人可以指导吗?

最佳答案

按照上述内容,您可以仅使用有限数量的资源来显示数千个元素(是的,这确实有点像享元模式)。这里有一些代码可以帮助你做你想做的事。

UntitledViewController 类仅包含一个 UIScroll 并将其自身设置为其委托(delegate)。我们有一个 NSArray,其中包含 NSString 实例作为数据模型(其中可能有数千个 NSString),我们希望使用水平滚动在 UILabel 中显示每个实例。当用户滚动时,我们会移动 UILabel,将一个放在左边,另一个放在右边,以便为下一个滚动事件做好一切准备。

这是界面,相当简单:

@interface UntitledViewController : UIViewController <UIScrollViewDelegate>
{
@private
UIScrollView *_scrollView;

NSArray *_objects;

UILabel *_detailLabel1;
UILabel *_detailLabel2;
UILabel *_detailLabel3;
}

@end

下面是该类的实现:

@interface UntitledViewController ()
- (void)replaceHiddenLabels;
- (void)displayLabelsAroundIndex:(NSInteger)index;
@end

@implementation UntitledViewController

- (void)dealloc
{
[_objects release];
[_scrollView release];
[_detailLabel1 release];
[_detailLabel2 release];
[_detailLabel3 release];
[super dealloc];
}

- (void)viewDidLoad
{
[super viewDidLoad];

_objects = [[NSArray alloc] initWithObjects:@"first", @"second", @"third",
@"fourth", @"fifth", @"sixth", @"seventh", @"eight", @"ninth", @"tenth", nil];

_scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 460.0)];
_scrollView.contentSize = CGSizeMake(320.0 * [_objects count], 460.0);
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.showsHorizontalScrollIndicator = YES;
_scrollView.alwaysBounceHorizontal = YES;
_scrollView.alwaysBounceVertical = NO;
_scrollView.pagingEnabled = YES;
_scrollView.delegate = self;

_detailLabel1 = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 460.0)];
_detailLabel1.textAlignment = UITextAlignmentCenter;
_detailLabel1.font = [UIFont boldSystemFontOfSize:30.0];
_detailLabel2 = [[UILabel alloc] initWithFrame:CGRectMake(320.0, 0.0, 320.0, 460.0)];
_detailLabel2.textAlignment = UITextAlignmentCenter;
_detailLabel2.font = [UIFont boldSystemFontOfSize:30.0];
_detailLabel3 = [[UILabel alloc] initWithFrame:CGRectMake(640.0, 0.0, 320.0, 460.0)];
_detailLabel3.textAlignment = UITextAlignmentCenter;
_detailLabel3.font = [UIFont boldSystemFontOfSize:30.0];

// We are going to show all the contents of the _objects array
// using only these three UILabel instances, making them jump
// right and left, replacing them as required:
[_scrollView addSubview:_detailLabel1];
[_scrollView addSubview:_detailLabel2];
[_scrollView addSubview:_detailLabel3];

[self.view addSubview:_scrollView];
}

- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[_scrollView flashScrollIndicators];
}

- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self displayLabelsAroundIndex:0];
}

- (void)didReceiveMemoryWarning
{
// Here you could release the data source, but make sure
// you rebuild it in a lazy-loading way as soon as you need it again...
[super didReceiveMemoryWarning];
}

#pragma mark -
#pragma mark UIScrollViewDelegate methods

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
// Do some initialization here, before the scroll view starts moving!
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self replaceHiddenLabels];
}

- (void)displayLabelsAroundIndex:(NSInteger)index
{
NSInteger count = [_objects count];
if (index >= 0 && index < count)
{
NSString *text = [_objects objectAtIndex:index];
_detailLabel1.frame = CGRectMake(320.0 * index, 0.0, 320.0, 460.0);
_detailLabel1.text = text;
[_scrollView scrollRectToVisible:CGRectMake(320.0 * index, 0.0, 320.0, 460.0) animated:NO];

if (index < (count - 1))
{
text = [_objects objectAtIndex:(index + 1)];
_detailLabel2.frame = CGRectMake(320.0 * (index + 1), 0.0, 320.0, 460.0);
_detailLabel2.text = text;
}

if (index > 0)
{
text = [_objects objectAtIndex:(index - 1)];
_detailLabel3.frame = CGRectMake(320.0 * (index - 1), 0.0, 320.0, 460.0);
_detailLabel3.text = text;
}
}
}

- (void)replaceHiddenLabels
{
static const double pageWidth = 320.0;
NSInteger currentIndex = ((_scrollView.contentOffset.x - pageWidth) / pageWidth) + 1;

UILabel *currentLabel = nil;
UILabel *previousLabel = nil;
UILabel *nextLabel = nil;

if (CGRectContainsPoint(_detailLabel1.frame, _scrollView.contentOffset))
{
currentLabel = _detailLabel1;
previousLabel = _detailLabel2;
nextLabel = _detailLabel3;
}
else if (CGRectContainsPoint(_detailLabel2.frame, _scrollView.contentOffset))
{
currentLabel = _detailLabel2;
previousLabel = _detailLabel1;
nextLabel = _detailLabel3;
}
else
{
currentLabel = _detailLabel3;
previousLabel = _detailLabel1;
nextLabel = _detailLabel2;
}

currentLabel.frame = CGRectMake(320.0 * currentIndex, 0.0, 320.0, 460.0);
currentLabel.text = [_objects objectAtIndex:currentIndex];

// Now move the other ones around
// and set them ready for the next scroll
if (currentIndex < [_objects count] - 1)
{
nextLabel.frame = CGRectMake(320.0 * (currentIndex + 1), 0.0, 320.0, 460.0);
nextLabel.text = [_objects objectAtIndex:(currentIndex + 1)];
}

if (currentIndex >= 1)
{
previousLabel.frame = CGRectMake(320.0 * (currentIndex - 1), 0.0, 320.0, 460.0);
previousLabel.text = [_objects objectAtIndex:(currentIndex - 1)];
}
}

@end

希望这对您有所帮助!

关于iphone - 如何实现具有 1000+ 个 subview 的 UIScrollView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2079225/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com