1

私はこの問題にしばらく苦労してきましたが、明確な答えはないようです。誰かがこれを理解したかどうか私に知らせてください。

画面の中央に写真を表示したいUIScrollView(画像は縦向きまたは横向きの場合があります)。

写真アプリのように、画像の端までしか画像をズームおよびパンできないようにしたい。

メソッドのを変更してみましたがcontentInsetviewDidEndZoomingそのような方法でうまくいきましたが、いくつかの不具合があります。

またimageView、と同じサイズにしてscrollView、画像を中央に配置してみました。問題は、ズームすると、画像全体imageViewをスクロールでき、画像の一部がビューからスクロールアウトする可能性があることです。

ここで同様の投稿を見つけて最善の回避策を示しましたが、実際の答えは見つかりませんでした。

写真アプリのように、UIImageViewを中央に配置したUIScrollView

4

3 に答える 3

2

このコードは、iOSのほとんどのバージョンで動作するはずです(3.1以降で動作することがテストされています)。

これは、PhotoScrollアプリのAppleWWDCコードに基づいています。

以下を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;
}
于 2010-08-13T16:54:32.410 に答える
2

コンテンツを中央に配置するためのエレガントな方法の1つUISCrollViewは、これです。

のcontentSizeにオブザーバーを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です。

于 2009-11-03T17:26:39.157 に答える
1

これが私がこの問題のために思いつくことができる最良の解決策です。秘訣は、imageViewのフレームを常に再調整することです。これは、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];
}

これが、viewDidLoadメソッドで最小ズームスケールを計算する方法です。

CGSize photoSize = [temporaryImage size];
CGSize screenSize = [[self view] bounds].size;

CGFloat widthRatio = screenSize.width / photoSize.width;
CGFloat heightRatio = screenSize.height / photoSize.height;
initialZoom = (widthRatio > heightRatio) ? heightRatio : widthRatio;
[myScrollView setMinimumZoomScale:initialZoom];
[myScrollView setZoomScale:initialZoom];
[myScrollView setMaximumZoomScale:3.0];
于 2009-10-04T02:19:14.517 に答える