我在UIScrollView中显示一系列图像.我非常想复制照片应用程序.
我目前的架构是:
所以我在父UIScrollView中基本上有一行UIScrollViews.
父UIScrollView启用了分页,因此我可以在页面之间滚动而不会出现任何问题.
问题是如何无缝平移放大的图像.我已经覆盖了viewForZoomingInScrollView方法,以返回适当的UIImageView当用户捏输入/输出. 如果缩放比例大于1,我已经覆盖了scrollViewDidEndZooming将父视图的canCancelContentTouches属性设置为的方法NO.
因此用户可以平移图像.但是,在将触摸事件发送到子视图之前,他们必须将手指放下一会儿才能超过父滚动视图的小延迟.此外,一旦用户在一个图像平移,下/预防和图像不当用户已经达到了当前图像的边界进入可视区域.
有任何想法吗?
谢谢.
好极了!我试图用一个UIScrollView解决问题,我想我找到了一个解决方案.
在用户开始缩放(in viewForZoomingInScrollView:)之前,我将滚动视图切换到缩放模式(删除所有其他页面,重置内容大小和偏移).当用户缩小到1.00(in scrollViewDidEndZooming:withView:atScale:)时,我切换回分页视图(添加所有页面,调整内容大小和偏移).
这是一个简单的视图控制器的代码,它就是这样做的.此示例在三个大型UIImageView之间切换,缩放和平移.
请注意,只需要一个具有少量功能的视图控制器,无需子类化UIScrollView等.
typedef enum {
ScrollViewModeNotInitialized, // view has just been loaded
ScrollViewModePaging, // fully zoomed out, swiping enabled
ScrollViewModeZooming, // zoomed in, panning enabled
ScrollViewModeAnimatingFullZoomOut, // fully zoomed out, animations not yet finished
ScrollViewModeInTransition, // during the call to setPagingMode to ignore scrollViewDidScroll events
} ScrollViewMode;
@interface ScrollingMadnessViewController : UIViewController <UIScrollViewDelegate> {
UIScrollView *scrollView;
NSArray *pageViews;
NSUInteger currentPage;
ScrollViewMode scrollViewMode;
}
@end
@implementation ScrollingMadnessViewController
- (void)setPagingMode {
NSLog(@"setPagingMode");
if (scrollViewMode != ScrollViewModeAnimatingFullZoomOut && scrollViewMode != ScrollViewModeNotInitialized)
return; // setPagingMode is called after a delay, so something might have changed since it was scheduled
scrollViewMode = ScrollViewModeInTransition; // to ignore scrollViewDidScroll when setting contentOffset
// reposition pages side by side, add them back to the view
CGSize pageSize = scrollView.frame.size;
NSUInteger page = 0;
for (UIView *view in pageViews) {
if (!view.superview)
[scrollView addSubview:view];
view.frame = CGRectMake(pageSize.width * page++, 0, pageSize.width, pageSize.height);
}
scrollView.pagingEnabled = YES;
scrollView.showsVerticalScrollIndicator = scrollView.showsHorizontalScrollIndicator = NO;
scrollView.contentSize = CGSizeMake(pageSize.width * [pageViews count], pageSize.height);
scrollView.contentOffset = CGPointMake(pageSize.width * currentPage, 0);
scrollViewMode = ScrollViewModePaging;
}
- (void)setZoomingMode {
NSLog(@"setZoomingMode");
scrollViewMode = ScrollViewModeInTransition; // to ignore scrollViewDidScroll when setting contentOffset
CGSize pageSize = scrollView.frame.size;
// hide all pages besides the current one
NSUInteger page = 0;
for (UIView *view in pageViews)
if (currentPage != page++)
[view removeFromSuperview];
// move the current page to (0, 0), as if no other pages ever existed
[[pageViews objectAtIndex:currentPage] setFrame:CGRectMake(0, 0, pageSize.width, pageSize.height)];
scrollView.pagingEnabled = NO;
scrollView.showsVerticalScrollIndicator = scrollView.showsHorizontalScrollIndicator = YES;
scrollView.contentSize = pageSize;
scrollView.contentOffset = CGPointZero;
scrollViewMode = ScrollViewModeZooming;
}
- (void)loadView {
CGRect frame = [UIScreen mainScreen].applicationFrame;
scrollView = [[UIScrollView alloc] initWithFrame:frame];
scrollView.delegate = self;
scrollView.maximumZoomScale = 2.0f;
scrollView.minimumZoomScale = 1.0f;
UIImageView *imageView1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"red.png"]];
UIImageView *imageView2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"green.png"]];
UIImageView *imageView3 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"yellow-blue.png"]];
// in a real app, you most likely want to have an array of view controllers, not views;
// also should be instantiating those views and view controllers lazily
pageViews = [[NSArray alloc] initWithObjects:imageView1, imageView2, imageView3, nil];
self.view = scrollView;
}
- (void)setCurrentPage:(NSUInteger)page {
if (page == currentPage)
return;
currentPage = page;
// in a real app, this would be a good place to instantiate more view controllers -- see SDK examples
}
- (void)viewDidLoad {
scrollViewMode = ScrollViewModeNotInitialized;
[self setPagingMode];
}
- (void)viewDidUnload {
[pageViews release]; // need to release all page views here; our array is created in loadView, so just releasing it
pageViews = nil;
}
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(setPagingMode) object:nil];
CGPoint offset = scrollView.contentOffset;
NSLog(@"scrollViewDidScroll: (%f, %f)", offset.x, offset.y);
if (scrollViewMode == ScrollViewModeAnimatingFullZoomOut && ABS(offset.x) < 1e-5 && ABS(offset.y) < 1e-5)
// bouncing is still possible (and actually happened for me), so wait a bit more to be sure
[self performSelector:@selector(setPagingMode) withObject:nil afterDelay:0.1];
else if (scrollViewMode == ScrollViewModePaging)
[self setCurrentPage:roundf(scrollView.contentOffset.x / scrollView.frame.size.width)];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)aScrollView {
if (scrollViewMode != ScrollViewModeZooming)
[self setZoomingMode];
return [pageViews objectAtIndex:currentPage];
}
- (void)scrollViewDidEndZooming:(UIScrollView *)aScrollView withView:(UIView *)view atScale:(float)scale {
NSLog(@"scrollViewDidEndZooming: scale = %f", scale);
if (fabsf(scale - 1.0) < 1e-5) {
if (scrollView.zoomBouncing)
NSLog(@"scrollViewDidEndZooming, but zoomBouncing is still true!");
// cannot call setPagingMode now because scrollView will bounce after a call to this method, resetting contentOffset to (0, 0)
scrollViewMode = ScrollViewModeAnimatingFullZoomOut;
// however sometimes bouncing will not take place
[self performSelector:@selector(setPagingMode) withObject:nil afterDelay:0.2];
}
}
@end
Run Code Online (Sandbox Code Playgroud)
可运行的示例项目可从http://github.com/andreyvit/ScrollingMadness/获得(如果您不使用Git,只需单击那里的"下载"按钮).那里有一个自述文件,解释了代码编写原理的原因.
(该示例项目还说明了如何以编程方式缩放滚动视图,并且具有封装解决方案的ZoomScrollView类.它是一个整洁的类,但不需要此技巧.如果您想要一个不使用ZoomScrollView的示例,在提交历史记录中返回一些提交.)
PS为了完整起见,有TTScrollView - UIScrollView从头开始重新实现.它是着名的Three20图书馆的一部分.我不喜欢它对用户的感觉,但它确实使得实现分页/滚动/缩放变得简单.
PPS Apple的真实照片应用程序具有SDK前代码并使用SDK之前的类.人们可以在PhotoLibrary框架内发现从UIScrollView的SDK前版本变体派生的两个类,但是不清楚他们做了什么(并且他们做了很多).我很容易相信这种效果在SDK之前的版本中更难以实现.
我必须做一个类似的设置,但我基本上定制了整个事情。我不确定当您到达边缘时,您将如何解决将触摸事件从子 UIScrollView “传递”到父 UISscrollView 的问题。您可以尝试在父 UIScrollView 中覆盖 UITouchesBegan:withEvent: ,然后直接转储到子视图。祝你好运!
| 归档时间: |
|
| 查看次数: |
22797 次 |
| 最近记录: |