programing

UIScroll View의 중앙 콘텐츠(작은 경우)

goodsources 2023. 4. 16. 15:01
반응형

UIScroll View의 중앙 콘텐츠(작은 경우)

는 나나 a a a가 있다UIImageView a UIScrollView을 사용하다스크롤 뷰의 이미지/콘텐츠가 스크롤 뷰보다 크면 모든 것이 정상적으로 동작합니다.그러나 이미지가 스크롤 보기보다 작아지면 스크롤 보기의 왼쪽 상단 모서리에 고정됩니다.포토 앱처럼 중심을 잡고 싶다.

UIScrollView더작작 때심 심심 ?? ???

저는 아이폰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)];
}

내게 아주 간단한 해결책이 있어!ScrollViewDelegate를 확대하면서 서브뷰(이미지뷰)의 중심을 갱신하기만 하면 됩니다.확대 이미지가 스크롤 뷰보다 작으면 하위 뷰를 조정합니다. 그렇지 않으면 중앙이 (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);
}

@EvelynCordner의 답변은 내 앱에서 가장 잘 작동했다.다른 옵션보다 훨씬 적은 코드입니다.

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 = UIEdgeInsets(top: offsetY, left: offsetX, bottom: 0, right: 0)
}

좋아요, 저는 지난 이틀간 이 문제와 씨름해왔고, 마침내 꽤 신뢰할 수 있는 (지금까지...) 해결책을 찾아냈기 때문에 이 문제를 공유하고 다른 사람들에게 고통을 덜어야겠다고 생각했습니다.:) 이 솔루션에 문제가 있는 경우는, 외쳐 주세요!

StackOverflow 검색, Apple Developer Forums, ScrollingMadness, ScrollTestSuite 등의 코드를 살펴봤습니다.UIImageView 프레임을 확대하여 ViewController에서 UIScrollView의 오프셋이나 삽입을 재생해 보았습니다만, (다른 사람도 알고 있듯이) 잘 되는 것은 없었습니다.

곰곰이 생각해본 후, 나는 몇 가지 다른 각도를 시도했다.

  1. UIImageView를 서브클래싱하여 자신의 크기를 동적으로 변경했습니다.이것은 전혀 동작하지 않았습니다.
  2. UIScroll View를 서브클래싱하여 자체 콘텐츠를 동적으로 변경하는 오프셋 - 이 제품이 가장 좋은 제품인 것 같습니다.

이 서브클래스의 UIScrollView 메서드에서는 contentOffset 뮤테이터를 오버라이드하여 이미지가 뷰포트보다 작은 크기일 때 {0,0}을(를) 설정하지 않도록 합니다.대신 이미지가 뷰포트에 집중되도록 오프셋을 설정합니다.지금까지는 항상 효과가 있는 것 같습니다.와이드, 키, 작은, 큰 이미지로 확인했지만, 「작동하지만, 최소 줌 브레이크로 핀치」의 문제는 없습니다.

이 솔루션을 사용하는 프로젝트의 예를 github에 업로드했습니다.http://github.com/nyoron/NYOBetterZoom 에서 찾을 수 있습니다.

자동 레이아웃을 사용하는 스크롤 뷰에 가장 적합한 솔루션의 경우 스크롤 뷰의 하위 뷰 프레임을 업데이트하는 대신 스크롤 뷰의 컨텐츠 삽입을 사용하십시오.

- (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);
}

이 코드는 대부분의 iOS 버전에서 작동해야 합니다(3.1 이상에서 작동하도록 테스트됨).

포토 컨트롤러의 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;
}

currently위 위중 。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 데모에서 확인할 수 있습니다.

하루 종일 이 문제와 씨름하다가 다음과 같은 스크롤뷰디드엔드줌잉: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);
}

이렇게 하면 이미지가 화면보다 작아도 주위에 충분한 공간이 있으므로 원하는 위치에 이미지를 배치할 수 있습니다.

(UIScroll View에 이미지를 유지하기 위한 UIImageView가 포함되어 있다고 가정합니다.)

기본적으로 이미지 뷰의 너비/높이가 화면 너비/높이보다 작은지 여부를 확인하고, 만약 그렇다면 화면의 절반 너비/높이 인셋을 작성합니다(이미지를 화면 경계 밖으로 내보내려면 이 크기를 크게 할 수 있습니다).

이는 UIScroll ViewDelegate 메서드이므로 빌드 문제가 발생하지 않도록 뷰 컨트롤러 선언에 추가하는 것을 잊지 마십시오.

ifcontentInset하다스크롤뷰의 콘텐츠를 중앙으로 이동시키는 데 사용할 수 있습니다.

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에서 콘텐츠를 드래그 앤 드롭하기만 하면 됩니다.

애플은 2010년 WWDC 세션 비디오를 아이폰 개발자 프로그램의 모든 회원들에게 공개했다.화제의 하나는, 사진 앱을 어떻게 만들었는지입니다!!!그들은 비슷한 앱을 단계별로 만들어 모든 코드를 무료로 이용할 수 있게 했다.

프라이빗 API도 사용하지 않습니다.비공개 계약 때문에 여기에 코드를 넣을 수 없지만 샘플 코드 다운로드 링크입니다.액세스하려면 아마 로그인해야 합니다.

http://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wa/getSoftware?code=y&source=x&bundleID=20645

다음은 iTunes WWDC 페이지 링크입니다.

http://insideapple.apple.com/redir/cbx-cgi.do?v=2&la=en&lc=&a=kGSol9sgPHP%2BtlWtLp%2BEP%2FnxnZarjWJglPBZRHd3oDbACudP51JNGS8KlsFgxZto9X%2BTsnqSbeUSWX0doe%2Fzv%2FN5XV55%2FomsyfRgFBysOnIVggO%2Fn2p%2BiweDK%2F%2FmsIXj

아아 、 이이 、 은과은은과효 。는 의의 of of of of의 .UIScrollView「 」를 .UIImageView표시하고 있습니다.UIScrollView대 content 、 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);
}

이미지를 미 ever ever ever ever ever ever ever ever ever 。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;
}

이 두 가지 방법으로 사진 앱과 같은 동작을 할 수 있습니다.

이 방법은 계층에 뷰를 추가하는 것입니다.

UIScrollView -> UIView -> UIImageView

의 이름을 대세요.UIView UIScrollView 중앙, 중앙, 중앙, 중앙, 중앙으로UIImageView그 안에.

딜러를 사용하여 하위 분류하지 않고 승인된 답변만 신속하게 제공합니다.

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)
}

위의 몇 가지 답변이 맞는 것은 알지만, 몇 가지 설명과 함께 답변을 드리려고 합니다.댓글을 보시면 저희가 왜 이러는지 알 수 있을 거예요

때 다음 합니다.「 ScrollView 」는 「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)

그런 다음 vSontent를 꼬집을 때 중앙에 놓기 위해 다음 코드를 작성합니다.

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)
}

<<고객명>> 은 <고객명>>을 보실 수 .contentSize키 값 및 UIScrollView를 합니다.contentInset whenevercontentSize스크롤 뷰 크기보다 작게 변경합니다.

UISCrollView★★★★★★★★★★★★★★★★★★.

콘텐츠에 옵서버 1개 추가UIScrollView이 메서드는 콘텐츠가 변경될 때마다 호출됩니다.

[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

이것은 스크롤 뷰 내의 모든 뷰에서 잘 작동하는 문제에 대한 저의 해결책입니다.

-(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];
  }
}

여기엔 많은 해결책이 있지만 난 위험을 감수할 거야이것은 두 가지 이유로 좋습니다. 즉, 진행 중인 이미지 뷰 프레임 업데이트와 마찬가지로 확대/축소 기능을 방해하지 않으며, 원래의 스크롤 뷰 삽입(예를 들어 반투명 툴바의 우아한 처리를 위해 xib 또는 스토리보드에 정의됨)을 존중합니다.

먼저 작은 도우미를 정의합니다.

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 자체가 로드된 이미지 변수라고 가정함)

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];

스크롤 뷰: UIScroll ViewDelegate에서 스크롤 뷰:

- (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)
    );
}

방향 변경(UIScroll View 자체의 크기 조정에 대한 적절한 반응)은 아직 테스트하지 않았지만, 비교적 쉽게 수정할 수 있을 것입니다.

Erdemus가 게시한 솔루션은 효과가 있지만...scrollViewDidZoom 메서드가 호출되지 않고 이미지가 왼쪽 상단 모서리에 고정된 경우가 있습니다.간단한 해결책은 이미지를 처음 표시할 때 다음과 같이 메서드를 명시적으로 호출하는 것입니다.

[self scrollViewDidZoom: scrollView];

대부분의 경우 이 메서드를 두 번 호출할 수 있지만 이 항목의 다른 응답보다 깔끔한 솔루션입니다.

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; 
}

Apple의 포토 스크롤러 샘플 코드

애니메이션의 흐름을 좋게 하려면 , 설정.

self.scrollview.bouncesZoom = NO;

그리고 이 기능을 사용한다( 답변의 방법으로 중심을 찾는다).

- (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);
    }];
}

이것은 튕기는 효과를 발생시키지만, 사전에 어떠한 갑작스러운 움직임도 수반하지 않습니다.

사용하시는 inner imageView의 초기 폭(예: 300)이 특정되어 있어 초기 폭보다 작은 줌만으로 폭을 조정하고 싶은 경우에도 도움이 됩니다.

 func scrollViewDidZoom(scrollView: UIScrollView){
    if imageView.frame.size.width < 300{
        imageView.center.x = self.view.frame.width/2
    }
  }

이게 내가 이 일을 하는 현재의 방식이야.그것은 더 낫지만 여전히 완벽하지 않다.설정 시도:

 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
}

좋아요, 이 문제에 대한 꽤 좋은 해결책을 찾은 것 같아요.비결은 지속적으로 재조정하는 것입니다.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];
}

페이지 번호 부여를 해제하면 정상적으로 작동합니다.

scrollview.pagingEnabled = NO;

나도 똑같은 문제가 있었어.내가 해결한 방법은 이렇다.

이 코드는 다음에 의해 호출됩니다.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);

질문이 좀 오래되었지만 아직 문제가 남아 있습니다.Xcode 7에서 가장 위 항목의 수직 공간 제약 조건을 만들어 해결했습니다(이 경우,topLabelsuperViews」)로 이동합니다scrollView의 상부에 있습니다.IBOutlet 다음 를 다시 ScrollView).topLabel ★★★★★★★★★★★★★★★★★」bottomLabel

class MyViewController: UIViewController {

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var topLabel: UILabel!
    @IBOutlet weak var bottomLabel: UILabel!
    @IBOutlet weak var toTopConstraint: NSLayoutConstraint!

    override func viewDidLayoutSubviews() {
        let heightOfScrollViewContents = (topLabel.frame.origin.y + topLabel.frame.size.height - bottomLabel.frame.origin.y)
        // In my case abs() delivers the perfect result, but you could also check if the heightOfScrollViewContents is greater than 0.
        toTopConstraint.constant = abs((scrollView.frame.height - heightOfScrollViewContents) / 2)
    }

    func refreshContents() {
        // Set the label's text …

        self.view.layoutIfNeeded()
    }
}

- 서브클래스 'Swift'만UIScrollView이치노을 사용하다

import UIKit

class CenteringScrollView: UIScrollView {
    override func layoutSubviews() {
        super.layoutSubviews()

        if zoomScale < 1.0 {
            if let subview = self.subviews.first {
                subview.center.x = self.center.x
            }
        }
    }
}

언급URL : https://stackoverflow.com/questions/1316451/center-content-of-uiscrollview-when-smaller

반응형