gpt4 book ai didi

iPhone - 全屏 UIScrollView 向右启动,但重新定位在导航栏下方

转载 作者:行者123 更新时间:2023-12-03 18:58:58 26 4
gpt4 key购买 nike

我目前正在尝试实现一个照片选择器,就像照片应用程序一样,但具有自定义图像源。对于“照片滚动”部分,我使用了 Apple PhotoScroller 示例代码并对其进行了修改。主要区别之一是它现在嵌入了导航 Controller (这是 photoPicker 自己的导航 Controller ,而不是应用程序的导航 Controller ),并带有导航栏。我的状态栏和导航栏是半透明的,并且我在 photoPicker 中使用的所有 View Controller 上设置了wantFullScreenLayout = YES。看起来效果几乎很好。 “概览” View (显示所有相册照片的缩略图的 View )确实是全屏的,我必须手动偏移它,以便缩略图首先显示在导航栏下方。然而,对于滚动部分有一个小故障。对于那些不了解 photoScroller 示例代码的人,它与带有 UIScrollView 属性 (pagingScrollView) 的自定义 UIViewController (PhotoViewController) 以及一组带有 UIView 和 NSInteger 索引属性的自定义 UIScrollView (ImageScrollView) 配合使用。然后将 ImageScrollView 实例作为 PhotoScroller 的 subview 添加/删除。

下面是一些相关代码:

PhotoViewController.h

@interface PhotoViewController : UIViewController <UIScrollViewDelegate> {
UIScrollView *pagingScrollView;

NSMutableSet *recycledPages;
NSMutableSet *visiblePages;

IBOutlet UIToolbar *toolbar;
IBOutlet UIBarButtonItem *previousButtonItem;
IBOutlet UIBarButtonItem *nextButtonItem;

id<PhotoViewDataSource> dataSource;
}

@property(nonatomic, retain) UIScrollView *pagingScrollView;
@property(nonatomic, retain) NSMutableSet *recylcledPages;
@property(nonatomic, retain) NSMutableSet *visiblePages;

@property(nonatomic, retain) UIToolbar *toolbar;
@property(nonatomic, retain) UIBarButtonItem *previousButtonItem;
@property(nonatomic, retain) UIBarButtonItem *nextButtonItem;

@property(nonatomic, retain) id<PhotoViewDataSource> dataSource;

PhotoViewController.m

- (void)loadView 
{
self.wantsFullScreenLayout = YES;

// Configure the scrollView
CGRect pagingScrollViewFrame = [self frameForPagingScrollView];
pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame];
pagingScrollView.pagingEnabled = YES;
pagingScrollView.backgroundColor = [UIColor redColor];
pagingScrollView.showsVerticalScrollIndicator = NO;
pagingScrollView.showsHorizontalScrollIndicator = NO;
pagingScrollView.contentSize = CGSizeMake(pagingScrollViewFrame.size.width * [self.dataSource imageCount],
pagingScrollViewFrame.size.height);
//pagingScrollView.contentOffset = CGPointMake(0, 0);

pagingScrollView.delegate = self;
self.view = pagingScrollView;

// TODO ? Prepare to tile content
recycledPages = [[NSMutableSet alloc] init];
visiblePages = [[NSMutableSet alloc] init];
[self processPages];
}


- (void)processPages {

// Calculate which pages are visible
CGRect visibleBounds = pagingScrollView.bounds;
NSLog(@"PhotoViewController - processPages : frame = %@", NSStringFromCGRect(pagingScrollView.frame));
NSLog(@"pagingScrollView bounds = %@", NSStringFromCGRect(pagingScrollView.bounds));
NSLog(@"and contentSize = %@", NSStringFromCGSize(pagingScrollView.contentSize));

int firstNeededPageIndex = floorf(CGRectGetMinX(visibleBounds) / CGRectGetWidth(visibleBounds));
int lastNeededPageIndex = floorf((CGRectGetMaxX(visibleBounds)-1) / CGRectGetWidth(visibleBounds));
firstNeededPageIndex = MAX(firstNeededPageIndex, 0);
lastNeededPageIndex = MIN(lastNeededPageIndex, [dataSource imageCount] - 1);

if (lastNeededPageIndex >= 0) {

// Recycle no-longer-visible pages
for (ImageScrollView *page in visiblePages) {
if (page.index < firstNeededPageIndex || page.index > lastNeededPageIndex) {
[recycledPages addObject:page];
[page removeFromSuperview];
}
}
[visiblePages minusSet:recycledPages];

// add missing pages
for (int index = firstNeededPageIndex; index <= lastNeededPageIndex; index++) {
if (![self isDisplayingPageForIndex:index]) {
ImageScrollView *page = [self dequeueRecycledPage];
if (page == nil) {
page = [[[ImageScrollView alloc] init] autorelease];
}
[self configurePage:page forIndex:index];
NSLog(@"PhotoViewController - processPage 2 : bounds = %@", NSStringFromCGRect(pagingScrollView.bounds));
[pagingScrollView addSubview:page];
NSLog(@"PhotoViewController - processPage 3 : bounds = %@", NSStringFromCGRect(pagingScrollView.bounds));
[visiblePages addObject:page];
}
}
}
}

- (ImageScrollView *)dequeueRecycledPage {
ImageScrollView *page = [recycledPages anyObject];
if (page) {
[[page retain] autorelease];
[recycledPages removeObject:page];
}
return page;
}

- (BOOL)isDisplayingPageForIndex:(NSUInteger)index {
BOOL foundPage = NO;
for (ImageScrollView *page in visiblePages) {
if (page.index == index) {
foundPage = YES;
break;
}
}
return foundPage;
}

- (void)configurePage:(ImageScrollView *)page forIndex:(NSUInteger)index {
page.index = index;
page.frame = [self frameForPageAtIndex:index];

NSLog(@"PhotoViewController - configurePage : bounds = %@", NSStringFromCGRect(pagingScrollView.bounds));

[page displayImage:[dataSource imageForImageId:index]];

NSLog(@"PhotoViewController - configurePage 2 : bounds = %@", NSStringFromCGRect(pagingScrollView.bounds));
}


#pragma mark -
#pragma mark ScrollView delegate methods

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self processPages];
}


#pragma mark -
#pragma mark Frame calculations
#define PADDING 10

- (CGRect)frameForPagingScrollView {
CGRect frame = [[UIScreen mainScreen] bounds];
frame.origin.x -= PADDING;
frame.size.width += (2*PADDING);
return frame;
}

- (CGRect)frameForPageAtIndex:(NSUInteger)index {
CGRect pagingScrollViewFrame = [self frameForPagingScrollView];

CGRect pageFrame = pagingScrollViewFrame;
pageFrame.size.width -= (2 * PADDING);
pageFrame.origin.x = (pagingScrollViewFrame.size.width * index) + PADDING;
//pageFrame.origin.x = (pagingScrollViewFrame.size.width * index) - (PADDING*index*2);
return pageFrame;
}

ImageScrollView.h

@interface ImageScrollView : UIScrollView <UIScrollViewDelegate> {
UIView *imageView;
NSUInteger index;
}
@property (assign) NSUInteger index;

- (void)displayImage:(UIImage *)image;
//- (void)displayTiledImageNamed:(NSString *)imageName size:(CGSize)imageSize;
- (void)configureForImageSize:(CGSize)imageSize;

ImageScrollView.m

- (void)layoutSubviews 
{
[super layoutSubviews];

imageView.backgroundColor = [UIColor greenColor];
self.backgroundColor = [UIColor blueColor];

// center the image as it becomes smaller than the size of the screen

CGSize boundsSize = self.bounds.size;
CGRect frameToCenter = imageView.frame;

// center horizontally
if (frameToCenter.size.width < boundsSize.width)
frameToCenter.origin.x = (boundsSize.width - frameToCenter.size.width) / 2;
else
frameToCenter.origin.x = 0;

// center vertically
if (frameToCenter.size.height < boundsSize.height)
frameToCenter.origin.y = (boundsSize.height - frameToCenter.size.height) / 2;
else
frameToCenter.origin.y = 0;

imageView.frame = frameToCenter;
NSLog(@"imageView frame = %@", NSStringFromCGRect(frameToCenter));

if ([imageView isKindOfClass:[TilingView class]]) {
// to handle the interaction between CATiledLayer and high resolution screens, we need to manually set the
// tiling view's contentScaleFactor to 1.0. (If we omitted this, it would be 2.0 on high resolution screens,
// which would cause the CATiledLayer to ask us for tiles of the wrong scales.)
imageView.contentScaleFactor = 1.0;
}
}

#pragma mark -
#pragma mark UIScrollView delegate methods

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return imageView;
}

#pragma mark -
#pragma mark Configure scrollView to display new image (tiled or not)

- (void)displayImage:(UIImage *)image
{
// clear the previous imageView
[imageView removeFromSuperview];
[imageView release];
imageView = nil;

// reset our zoomScale to 1.0 before doing any further calculations
self.zoomScale = 1.0;

// make a new UIImageView for the new image
imageView = [[UIImageView alloc] initWithImage:image];
[self addSubview:imageView];

[self configureForImageSize:[image size]];
}

- (void)configureForImageSize:(CGSize)imageSize
{
CGSize boundsSize = [self bounds].size;

// set up our content size and min/max zoomscale
CGFloat xScale = boundsSize.width / imageSize.width; // the scale needed to perfectly fit the image width-wise
CGFloat yScale = boundsSize.height / imageSize.height; // the scale needed to perfectly fit the image height-wise
CGFloat minScale = MIN(xScale, yScale); // use minimum of these to allow the image to become fully visible

// on high resolution screens we have double the pixel density, so we will be seeing every pixel if we limit the
// maximum zoom scale to 0.5.
CGFloat maxScale = /*1.0 / */[[UIScreen mainScreen] scale];

// don't let minScale exceed maxScale. (If the image is smaller than the screen, we don't want to force it to be zoomed.)
if (minScale > maxScale) {
minScale = maxScale;
}

self.contentSize = imageSize;
self.maximumZoomScale = maxScale;
self.minimumZoomScale = minScale;
self.zoomScale = minScale; // start out with the content fully visible
}

我的问题是,当我第一次加载 PhotoViewController 实例时, pagingScrollView 偏移到 (0, -64) 像素的原点(我想是状态栏 + 导航栏的高度)。这会导致界面困惑,其中 ImageScrollView 出现在导航栏(原点 (0, 0))下方,即使其高度小于屏幕,也可以上下滚动。

通过一些日志和断点,我能够确定 pagingScrollView 边界在加载过程开始时没有问题。当我缩放 ImageScrollView 的图像以适合屏幕时,它们会发生变化。这会导致调用 viewForZoomingInScrollView 和scrollViewDidScroll 方法。 pagingScrollView 在这些调用期间发生偏移。

我尝试手动设置偏移量,但是当我在 processPages 中设置偏移量时,scrollView 无法再上下弹跳...

任何帮助将不胜感激!

干杯

PB

最佳答案

在您的特定情况下(即 PhotoViewController 被推送到 UINavigationController 堆栈上) - 导航栏将 contentInset 添加到 PhotoViewController 的 ScrollView 。这一切都得到了更好的解释herehere

也就是说,PhotoViewController View 与窗口边界不紧密配合,因此有向各个方向滚动的空间。

我找到了解决您问题的 2 种可能的解决方案。

1 - 您需要手动调整 pagingScrollViewcontentInset 以补偿导航栏和状态栏的高度。将其添加到PhotoViewController:

- (void)viewDidLoad {
[super viewDidLoad];

CGFloat topOffset = self.navigationController.navigationBar.frame.size.height + [[UIApplication sharedApplication] statusBarFrame].size.height;
pagingScrollView.contentInset = UIEdgeInsetsMake(-topOffset, 0.0, 0.0, 0.0);
}

2 - 由于只有 ScrollView 才有 contentInset,因此将 pagingScrollView 包装在普通的 UIView 中:

- (void)loadView {    
[self setWantsFullScreenLayout:YES];

CGRect pagingScrollViewFrame = [self frameForPagingScrollView];
photoView = [[UIView alloc] initWithFrame:pagingScrollViewFrame];
pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame];

// ... configure the pagingScrollView

[photoView addSubview:pagingScrollView];
self.view = photoView;

// ...
}

希望这有帮助!

关于iPhone - 全屏 UIScrollView 向右启动,但重新定位在导航栏下方,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3716620/

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