我在UIImageView
内有一个UIScrollView
,用于缩放和滚动。如果滚动视图的图像/内容大于滚动视图,则一切正常。但是,当图像变得小于滚动视图时,它会粘在滚动视图的左上角。我想让它保持中心,就像照片应用程序一样。
有关保持UIScrollView
内容较小的内容的任何想法或示例吗?
我正在使用iPhone 3.0。
以下代码几乎可以使用。如果在达到最小缩放级别后将其捏住,图像将返回左上角。
- (void)loadView {
[super loadView];
// set up main scroll view
imageScrollView = [[UIScrollView alloc] initWithFrame:[[self view] bounds]];
[imageScrollView setBackgroundColor:[UIColor blackColor]];
[imageScrollView setDelegate:self];
[imageScrollView setBouncesZoom:YES];
[[self view] addSubview:imageScrollView];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"WeCanDoIt.png"]];
[imageView setTag:ZOOM_VIEW_TAG];
[imageScrollView setContentSize:[imageView frame].size];
[imageScrollView addSubview:imageView];
CGSize imageSize = imageView.image.size;
[imageView release];
CGSize maxSize = imageScrollView.frame.size;
CGFloat widthRatio = maxSize.width / imageSize.width;
CGFloat heightRatio = maxSize.height / imageSize.height;
CGFloat initialZoom = (widthRatio > heightRatio) ? heightRatio : widthRatio;
[imageScrollView setMinimumZoomScale:initialZoom];
[imageScrollView setZoomScale:1];
float topInset = (maxSize.height - imageSize.height) / 2.0;
float sideInset = (maxSize.width - imageSize.width) / 2.0;
if (topInset < 0.0) topInset = 0.0;
if (sideInset < 0.0) sideInset = 0.0;
[imageScrollView setContentInset:UIEdgeInsetsMake(topInset, sideInset, -topInset, -sideInset)];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return [imageScrollView viewWithTag:ZOOM_VIEW_TAG];
}
/************************************** NOTE **************************************/
/* The following delegate method works around a known bug in zoomToRect:animated: */
/* In the next release after 3.0 this workaround will no longer be necessary */
/**********************************************************************************/
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
[scrollView setZoomScale:scale+0.01 animated:NO];
[scrollView setZoomScale:scale animated:NO];
// END Bug workaround
CGSize maxSize = imageScrollView.frame.size;
CGSize viewSize = view.frame.size;
float topInset = (maxSize.height - viewSize.height) / 2.0;
float sideInset = (maxSize.width - viewSize.width) / 2.0;
if (topInset < 0.0) topInset = 0.0;
if (sideInset < 0.0) sideInset = 0.0;
[imageScrollView setContentInset:UIEdgeInsetsMake(topInset, sideInset, -topInset, -sideInset)];
}
答案 0 :(得分:225)
我有一个非常简单的解决方案! 您只需在放大ScrollViewDelegate时更新子视图(imageview)的中心即可。 如果缩放图像小于scrollview,则调整subview.center else center为(0,0)。
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
UIView *subView = [scrollView.subviews objectAtIndex:0];
CGFloat offsetX = MAX((scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5, 0.0);
CGFloat offsetY = MAX((scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5, 0.0);
subView.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX,
scrollView.contentSize.height * 0.5 + offsetY);
}
答案 1 :(得分:37)
@EvelynCordner's answer是我应用中效果最好的那个。代码也少于其他选项。
如果有人需要,可以使用Swift版本:
func scrollViewDidZoom(_ scrollView: UIScrollView) {
let offsetX = max((scrollView.bounds.width - scrollView.contentSize.width) * 0.5, 0)
let offsetY = max((scrollView.bounds.height - scrollView.contentSize.height) * 0.5, 0)
scrollView.contentInset = UIEdgeInsetsMake(offsetY, offsetX, 0, 0)
}
答案 2 :(得分:25)
好吧,过去两天我一直在争吵,终于找到了一个非常可靠的(迄今为止......)解决方案,我认为我应该分享它并为其他人带来一些痛苦。 :)如果您确实发现此解决方案存在问题,请大声呼喊!
我基本上已经了解了其他人的所有内容:搜索StackOverflow,Apple Developer Forums,查看了three20,ScrollingMadness,ScrollTestSuite等的代码。我尝试放大UIImageView框架,玩UIScrollView的偏移量和/或来自ViewController等的插图,但没有任何效果很好(正如其他人也发现的那样)。
睡觉后,我尝试了几个不同的角度:
使用这个子类化UIScrollView方法,我覆盖了contentOffset mutator,因此当图像缩放比视口小时,它不会设置{0,0} - 而是设置偏移,使图像保持居中视口。到目前为止,似乎总是有效。我用宽大,高大,小巧的方式检查了它。大图像,并没有“工作,但捏最小缩放打破它”问题。
我已经将一个示例项目上传到使用此解决方案的github,您可以在此处找到它:http://github.com/nyoron/NYOBetterZoom
答案 3 :(得分:23)
此代码适用于大多数iOS版本(已经过测试,可以在3.1版本上运行)。
它基于photoscoller的Apple WWDC代码。
将以下内容添加到UIScrollView的子类中,并将tileContainerView替换为包含图像或切片的视图:
- (void)layoutSubviews {
[super layoutSubviews];
// center the image as it becomes smaller than the size of the screen
CGSize boundsSize = self.bounds.size;
CGRect frameToCenter = tileContainerView.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;
tileContainerView.frame = frameToCenter;
}
答案 4 :(得分:20)
对于更适合使用自动布局的滚动视图的解决方案,请使用滚动视图的内容插入,而不是更新滚动视图的子视图的帧。
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
CGFloat offsetX = MAX((scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5, 0.0);
CGFloat offsetY = MAX((scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5, 0.0);
self.scrollView.contentInset = UIEdgeInsetsMake(offsetY, offsetX, 0.f, 0.f);
}
答案 5 :(得分:19)
目前,我正在对UIScrollView
进行子类化并覆盖setContentOffset:
以根据contentSize
调整偏移量。它适用于捏合和编程缩放。
@implementation HPCenteringScrollView
- (void)setContentOffset:(CGPoint)contentOffset
{
const CGSize contentSize = self.contentSize;
const CGSize scrollViewSize = self.bounds.size;
if (contentSize.width < scrollViewSize.width)
{
contentOffset.x = -(scrollViewSize.width - contentSize.width) / 2.0;
}
if (contentSize.height < scrollViewSize.height)
{
contentOffset.y = -(scrollViewSize.height - contentSize.height) / 2.0;
}
[super setContentOffset:contentOffset];
}
@end
除了简短和甜美之外,此代码还可以比@Erdemus解决方案产生更加平滑的缩放。您可以在RMGallery演示中看到它。
答案 6 :(得分:12)
我花了一天时间来解决这个问题,最后实现了 scrollViewDidEndZooming:withView:atScale:,如下所示:
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
CGFloat viewWidth = view.frame.size.width;
CGFloat viewHeight = view.frame.size.height;
CGFloat x = 0;
CGFloat y = 0;
if(viewWidth < screenWidth) {
x = screenWidth / 2;
}
if(viewHeight < screenHeight) {
y = screenHeight / 2 ;
}
self.scrollView.contentInset = UIEdgeInsetsMake(y, x, y, x);
}
这可确保当图像小于屏幕时,周围仍有足够的空间,因此您可以将其放置在您想要的位置。
(假设你的UIScrollView包含一个UIImageView来保存图像)
基本上,这样做是检查你的图像视图的宽度/高度是否小于屏幕的宽度/高度,如果是这样的话,创建一个屏幕宽度/高度的一半的插图(如果你想要的话,你可以把它放大一些图像走出屏幕界限。)
请注意,由于这是 UIScrollViewDelegate 方法,因此请不要忘记将其添加到视图控制器的声明中,以避免出现构建问题。
答案 7 :(得分:7)
Apple已向iphone开发者计划的所有成员发布了2010 WWDC会话视频。讨论的主题之一是他们如何创建照片应用程序!他们逐步构建一个非常相似的应用程序,并使所有代码免费提供。
它也不使用私人api。由于非公开协议,我不能在此处放置任何代码,但这里是示例代码下载的链接。您可能需要登录才能获得访问权限。
并且,这是iTunes WWDC页面的链接:
答案 8 :(得分:3)
如果不需要contentInset
,则可以使用它来居中滚动视图的内容。
class ContentCenteringScrollView: UIScrollView {
override var bounds: CGRect {
didSet { updateContentInset() }
}
override var contentSize: CGSize {
didSet { updateContentInset() }
}
private func updateContentInset() {
var top = CGFloat(0)
var left = CGFloat(0)
if contentSize.width < bounds.width {
left = (bounds.width - contentSize.width) / 2
}
if contentSize.height < bounds.height {
top = (bounds.height - contentSize.height) / 2
}
contentInset = UIEdgeInsets(top: top, left: left, bottom: top, right: left)
}
}
这种方法的优点是您仍然可以使用contentLayoutGuide
将内容放置在滚动视图中
scrollView.addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
imageView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
imageView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
imageView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
imageView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor)
])
或只是将内容拖放到Xcode的Interface Builder中。
答案 9 :(得分:2)
好的,这个解决方案对我有用。我有一个UIScrollView
的子类,它引用了它显示的UIImageView
。每当UIScrollView
缩放时,都会调整contentSize属性。我在设定者中适当地缩放UIImageView
并调整其中心位置。
-(void) setContentSize:(CGSize) size{
CGSize lSelfSize = self.frame.size;
CGPoint mid;
if(self.zoomScale >= self.minimumZoomScale){
CGSize lImageSize = cachedImageView.initialSize;
float newHeight = lImageSize.height * self.zoomScale;
if (newHeight < lSelfSize.height ) {
newHeight = lSelfSize.height;
}
size.height = newHeight;
float newWidth = lImageSize.width * self.zoomScale;
if (newWidth < lSelfSize.width ) {
newWidth = lSelfSize.width;
}
size.width = newWidth;
mid = CGPointMake(size.width/2, size.height/2);
}
else {
mid = CGPointMake(lSelfSize.width/2, lSelfSize.height/2);
}
cachedImageView.center = mid;
[super setContentSize:size];
[self printLocations];
NSLog(@"zoom %f setting size %f x %f",self.zoomScale,size.width,size.height);
}
Evertime我在UIScrollView
上设置图像我调整了它的大小。滚动视图中的UIScrollView
也是我创建的自定义类。
-(void) resetSize{
if (!scrollView){//scroll view is view containing imageview
return;
}
CGSize lSize = scrollView.frame.size;
CGSize lSelfSize = self.image.size;
float lWidth = lSize.width/lSelfSize.width;
float lHeight = lSize.height/lSelfSize.height;
// choose minimum scale so image width fits screen
float factor = (lWidth<lHeight)?lWidth:lHeight;
initialSize.height = lSelfSize.height * factor;
initialSize.width = lSelfSize.width * factor;
[scrollView setContentSize:lSize];
[scrollView setContentOffset:CGPointZero];
scrollView.userInteractionEnabled = YES;
}
通过这两种方法,我可以拥有一个与照片应用程序一样的视图。
答案 10 :(得分:1)
这里有很多解决方案,但我冒险把它放在这里。这有两个原因:它不会影响缩放体验,就像更新正在进行的图像视图帧一样,并且它还尊重原始滚动视图插图(例如,在xib或storyboard中定义,以便优雅地处理半透明工具栏等) 。
首先,定义一个小帮手:
CGSize CGSizeWithAspectFit(CGSize containerSize, CGSize contentSize) {
CGFloat containerAspect = containerSize.width / containerSize.height,
contentAspect = contentSize.width / contentSize.height;
CGFloat scale = containerAspect > contentAspect
? containerSize.height / contentSize.height
: containerSize.width / contentSize.width;
return CGSizeMake(contentSize.width * scale, contentSize.height * scale);
}
要保留原始插图,请定义字段:
UIEdgeInsets originalScrollViewInsets;
在viewDidLoad的某处填写:
originalScrollViewInsets = self.scrollView.contentInset;
将UIImageView放入UIScrollView(假设UIImage本身位于loadedImage var中):
CGSize containerSize = self.scrollView.bounds.size;
containerSize.height -= originalScrollViewInsets.top + originalScrollViewInsets.bottom;
containerSize.width -= originalScrollViewInsets.left + originalScrollViewInsets.right;
CGSize contentSize = CGSizeWithAspectFit(containerSize, loadedImage.size);
UIImageView *imageView = [[UIImageView alloc] initWithFrame:(CGRect) { CGPointZero, contentSize }];
imageView.autoresizingMask = UIViewAutoresizingNone;
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.image = loadedImage;
[self.scrollView addSubview:imageView];
self.scrollView.contentSize = contentSize;
[self centerImageViewInScrollView];
scrollViewDidZoom:来自UIScrollViewDelegate的滚动视图:
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
if (scrollView == self.scrollView) {
[self centerImageViewInScrollView];
}
}
最后,以自己为中心:
- (void)centerImageViewInScrollView {
CGFloat excessiveWidth = MAX(0.0, self.scrollView.bounds.size.width - self.scrollView.contentSize.width),
excessiveHeight = MAX(0.0, self.scrollView.bounds.size.height - self.scrollView.contentSize.height),
insetX = excessiveWidth / 2.0,
insetY = excessiveHeight / 2.0;
self.scrollView.contentInset = UIEdgeInsetsMake(
MAX(insetY, originalScrollViewInsets.top),
MAX(insetX, originalScrollViewInsets.left),
MAX(insetY, originalScrollViewInsets.bottom),
MAX(insetX, originalScrollViewInsets.right)
);
}
我还没有测试方向更改(即调整UIScrollView本身的正确反应),但修复它应该相对容易。
答案 11 :(得分:1)
如果您的内部imageView具有初始特定宽度(例如300),并且您只想将其宽度仅放在小于其初始宽度的缩放中心,这对您也有帮助。
func scrollViewDidZoom(scrollView: UIScrollView){
if imageView.frame.size.width < 300{
imageView.center.x = self.view.frame.width/2
}
}
答案 12 :(得分:1)
只是swift中的已批准答案,但没有使用委托
进行子类化func centerScrollViewContents(scrollView: UIScrollView) {
let contentSize = scrollView.contentSize
let scrollViewSize = scrollView.frame.size;
var contentOffset = scrollView.contentOffset;
if (contentSize.width < scrollViewSize.width) {
contentOffset.x = -(scrollViewSize.width - contentSize.width) / 2.0
}
if (contentSize.height < scrollViewSize.height) {
contentOffset.y = -(scrollViewSize.height - contentSize.height) / 2.0
}
scrollView.setContentOffset(contentOffset, animated: false)
}
// UIScrollViewDelegate
func scrollViewDidZoom(scrollView: UIScrollView) {
centerScrollViewContents(scrollView)
}
答案 13 :(得分:1)
要使动画流畅,请设置
self.scrollview.bouncesZoom = NO;
并使用此功能(使用this answer处的方法找到中心)
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale {
[UIView animateWithDuration:0.2 animations:^{
float offsetX = MAX((scrollView.bounds.size.width-scrollView.contentSize.width)/2, 0);
float offsetY = MAX((scrollView.bounds.size.height-scrollView.contentSize.height)/2, 0);
self.imageCoverView.center = CGPointMake(scrollView.contentSize.width*0.5+offsetX, scrollView.contentSize.height*0.5+offsetY);
}];
}
这会产生弹跳效果,但事先不会涉及任何突然的动作。
答案 14 :(得分:1)
Apple的Photo Scroller示例完全符合您的要求。将它放在您的UIScrollView子类中,并将_zoomView更改为您的UIImageView。
-(void)layoutSubviews{
[super layoutSubviews];
// center the zoom view as it becomes smaller than the size of the screen
CGSize boundsSize = self.bounds.size;
CGRect frameToCenter = self.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;
}
self.imageView.frame = frameToCenter;
}
答案 15 :(得分:1)
您可以观看UIScrollView的contentSize
属性(使用键值观察或类似),并在contentInset
更改为小于的时候自动调整contentSize
滚动视图。
答案 16 :(得分:1)
这是我对该问题的解决方案,对于滚动视图中的任何类型的视图都可以正常工作。
-(void)scrollViewDidZoom:(__unused UIScrollView *)scrollView
{
CGFloat top;
CGFloat left;
CGFloat bottom;
CGFloat right;
if (_scrollView.contentSize.width < scrollView.bounds.size.width) {
DDLogInfo(@"contentSize %@",NSStringFromCGSize(_scrollView.contentSize));
CGFloat width = (_scrollView.bounds.size.width-_scrollView.contentSize.width)/2.0;
left = width;
right = width;
}else {
left = kInset;
right = kInset;
}
if (_scrollView.contentSize.height < scrollView.bounds.size.height) {
CGFloat height = (_scrollView.bounds.size.height-_scrollView.contentSize.height)/2.0;
top = height;
bottom = height;
}else {
top = kInset;
right = kInset;
}
_scrollView.contentInset = UIEdgeInsetsMake(top, left, bottom, right);
if ([self.tiledScrollViewDelegate respondsToSelector:@selector(tiledScrollViewDidZoom:)])
{
[self.tiledScrollViewDelegate tiledScrollViewDidZoom:self];
}
}
答案 17 :(得分:1)
你会发现Erdemus发布的解决方案确实有效,但是......在某些情况下,不会调用scrollViewDidZoom方法&amp;你的图像粘在左上角。一个简单的解决方案是在最初显示图像时显式调用该方法,如下所示:
[self scrollViewDidZoom: scrollView];
在许多情况下,您可能会两次调用此方法,但这比本主题中的其他一些答案更清晰。
答案 18 :(得分:1)
将UISCrollView
的内容集中在一起的一种优雅方式就是这个。
将一位观察者添加到UIScrollView
的 contentSize 中,因此每次内容更改时都会调用此方法...
[myScrollView addObserver:delegate
forKeyPath:@"contentSize"
options:(NSKeyValueObservingOptionNew)
context:NULL];
现在用你的观察者方法:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
// Correct Object Class.
UIScrollView *pointer = object;
// Calculate Center.
CGFloat topCorrect = ([pointer bounds].size.height - [pointer viewWithTag:100].bounds.size.height * [pointer zoomScale]) / 2.0 ;
topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
topCorrect = topCorrect - ( pointer.frame.origin.y - imageGallery.frame.origin.y );
// Apply Correct Center.
pointer.center = CGPointMake(pointer.center.x,
pointer.center.y + topCorrect ); }
您应该更改[pointer
viewWithTag:100]
。替换你的
内容视图UIView
。
imageGallery
指向您的窗口大小。每当他的尺寸发生变化时,这将更正内容的中心。
注意:此内容效果不佳的唯一方法是使用UIScrollView
的标准缩放功能。
答案 19 :(得分:1)
我这样做的方法是在层次结构中添加一个额外的视图:
UIScrollView -> UIView -> UIImageView
为UIView
提供与UIScrollView
相同的宽高比,并将UIImageView
置于其中。
答案 20 :(得分:0)
只需禁用分页,即可正常使用:
scrollview.pagingEnabled = NO;
答案 21 :(得分:0)
我遇到了完全相同的问题。这是我解决的方法
此代码应作为scrollView:DidScroll:
CGFloat imageHeight = self.imageView.frame.size.width * self.imageView.image.size.height / self.imageView.image.size.width;
BOOL imageSmallerThanContent = (imageHeight < self.scrollview.frame.size.height) ? YES : NO;
CGFloat topOffset = (self.imageView.frame.size.height - imageHeight) / 2;
// If image is not large enough setup content offset in a way that image is centered and not vertically scrollable
if (imageSmallerThanContent) {
topOffset = topOffset - ((self.scrollview.frame.size.height - imageHeight)/2);
}
self.scrollview.contentInset = UIEdgeInsetsMake(topOffset * -1, 0, topOffset * -1, 0);
答案 22 :(得分:0)
虽然这个问题有点陈旧但问题仍然存在。我通过将最上面的项目(在本例中为topLabel
)的垂直空间约束设置为superViews(scrollView
)顶部{{1},在 Xcode 7 中解决了它然后每次内容根据scrollView的子视图(IBOutlet
和topLabel
)的高度更改时重新计算其常量。
bottomLabel
答案 23 :(得分:0)
这是我正在做这项工作的当前方式。它更好但仍然不完美。尝试设置:
myScrollView.bouncesZoom = YES;
解决问题,在minZoomScale
时,视图不居中。
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGSize screenSize = [[self view] bounds].size;//[[UIScreen mainScreen] bounds].size;//
CGSize photoSize = [yourImage size];
CGFloat topInset = (screenSize.height - photoSize.height * [myScrollView zoomScale]) / 2.0;
CGFloat sideInset = (screenSize.width - photoSize.width * [myScrollView zoomScale]) / 2.0;
if (topInset < 0.0)
{ topInset = 0.0; }
if (sideInset < 0.0)
{ sideInset = 0.0; }
[myScrollView setContentInset:UIEdgeInsetsMake(topInset, sideInset, -topInset, -sideInset)];
ApplicationDelegate *appDelegate = (ApplicationDelegate *)[[UIApplication sharedApplication] delegate];
CGFloat scrollViewHeight; //Used later to calculate the height of the scrollView
if (appDelegate.navigationController.navigationBar.hidden == YES) //If the NavBar is Hidden, set scrollViewHeight to 480
{ scrollViewHeight = 480; }
if (appDelegate.navigationController.navigationBar.hidden == NO) //If the NavBar not Hidden, set scrollViewHeight to 360
{ scrollViewHeight = 368; }
imageView.frame = CGRectMake(0, 0, CGImageGetWidth(yourImage)* [myScrollView zoomScale], CGImageGetHeight(yourImage)* [myScrollView zoomScale]);
[imageView setContentMode:UIViewContentModeCenter];
}
此外,我执行以下操作以防止图像在缩小后粘在一边。
- (void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
myScrollView.frame = CGRectMake(0, 0, 320, 420);
//put the correct parameters for your scroll view width and height above
}
答案 24 :(得分:0)
好的,我想我找到了一个很好的解决方案。诀窍是不断重新调整imageView's
帧。我觉得这比不断调整contentInsets
或contentOffSets
要好得多。我不得不添加一些额外的代码来容纳纵向和横向图像。
以下是代码:
- (void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
CGSize screenSize = [[self view] bounds].size;
if (myScrollView.zoomScale <= initialZoom +0.01) //This resolves a problem with the code not working correctly when zooming all the way out.
{
imageView.frame = [[self view] bounds];
[myScrollView setZoomScale:myScrollView.zoomScale +0.01];
}
if (myScrollView.zoomScale > initialZoom)
{
if (CGImageGetWidth(temporaryImage.CGImage) > CGImageGetHeight(temporaryImage.CGImage)) //If the image is wider than tall, do the following...
{
if (screenSize.height >= CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the height of the screen is greater than the zoomed height of the image do the following...
{
imageView.frame = CGRectMake(0, 0, 320*(myScrollView.zoomScale), 368);
}
if (screenSize.height < CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the height of the screen is less than the zoomed height of the image do the following...
{
imageView.frame = CGRectMake(0, 0, 320*(myScrollView.zoomScale), CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]);
}
}
if (CGImageGetWidth(temporaryImage.CGImage) < CGImageGetHeight(temporaryImage.CGImage)) //If the image is taller than wide, do the following...
{
CGFloat portraitHeight;
if (CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale] < 368)
{ portraitHeight = 368;}
else {portraitHeight = CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale];}
if (screenSize.width >= CGImageGetWidth(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the width of the screen is greater than the zoomed width of the image do the following...
{
imageView.frame = CGRectMake(0, 0, 320, portraitHeight);
}
if (screenSize.width < CGImageGetWidth (temporaryImage.CGImage) * [myScrollView zoomScale]) //If the width of the screen is less than the zoomed width of the image do the following...
{
imageView.frame = CGRectMake(0, 0, CGImageGetWidth(temporaryImage.CGImage) * [myScrollView zoomScale], portraitHeight);
}
}
[myScrollView setZoomScale:myScrollView.zoomScale -0.01];
}
答案 25 :(得分:0)
我知道上面的一些答案是正确的,但是我只想对我的答案进行一些解释,这些评论将使您理解我们为什么这样做。
当我第一次加载scrollView时,我编写了以下代码使其居中,请注意,我们先设置contentOffset
,然后设置contentInset
scrollView.maximumZoomScale = 8
scrollView.minimumZoomScale = 1
// set vContent frame
vContent.frame = CGRect(x: 0,
y: 0 ,
width: vContentWidth,
height: vContentWidth)
// set scrollView.contentSize
scrollView.contentSize = vContent.frame.size
//on the X direction, if contentSize.width > scrollView.bounds.with, move scrollView from 0 to offsetX to make it center(using `scrollView.contentOffset`)
// if not, don't need to set offset, but we need to set contentInset to make it center.(using `scrollView.contentInset`)
// so does the Y direction.
let offsetX = max((scrollView.contentSize.width - scrollView.bounds.width) * 0.5, 0)
let offsetY = max((scrollView.contentSize.height - scrollView.bounds.height) * 0.5, 0)
scrollView.contentOffset = CGPoint(x: offsetX, y: offsetY)
let topX = max((scrollView.bounds.width - scrollView.contentSize.width) * 0.5, 0)
let topY = max((scrollView.bounds.height - scrollView.contentSize.height) * 0.5, 0)
scrollView.contentInset = UIEdgeInsets(top: topY, left: topX, bottom: 0, right: 0)
然后,当我捏住vContent时,我编写以下代码以使其居中。
func scrollViewDidZoom(_ scrollView: UIScrollView) {
//we just need to ensure that the content is in the center when the contentSize is less than scrollView.size.
let topX = max((scrollView.bounds.width - scrollView.contentSize.width) * 0.5, 0)
let topY = max((scrollView.bounds.height - scrollView.contentSize.height) * 0.5, 0)
scrollView.contentInset = UIEdgeInsets(top: topY, left: topX, bottom: 0, right: 0)
}