2012-11-30 3 views
4

iOS 용 최신 Expedia 앱에서는 머리를 감싸는 데 매우 흥미로운 영향을줍니다. 내가 아는 무한히 스크롤하는 서브 뷰의 두 개의 컬럼은 두 개의 스크롤 뷰로 수행 될 수 있습니다. 흥미로운 점은 전반적인 스크롤 뷰에는 정적 인 상태로 유지되고 각 하위 뷰 셀 사이의 틈에서 볼 수있는 린넨 배경이있는 것으로 나타났습니다. 정말 멋진 부분은 하위보기가 다른 배경을 유지한다는 것입니다. 아래 스크린 샷에서 도시 스카이 라인 이미지입니다. 하위보기가 스크롤되면 도시 이미지는 하위보기 셀 뒤에 만 볼 수 있습니다. 그것은 마술 트릭 일종의 것으로 보이지만 나는 그 효과가 어떻게 이루어 졌는지 알 수 없다. 동일한 결과를 얻으려면 어떻게해야합니까?정적 하위 뷰 배경 이미지 효과

기본적으로 작은 창으로 작용하고 린넨을 표시하지 않는 하위 뷰 뒤에 정적 배경을 표시 할 수 있습니다. 린넨은 세포 주위에만 보여야합니다.

응용 프로그램을 다운로드하고 비행기 모드를 치고 직접 사용해 볼 수 있습니다. 여기 enter image description here

는 또 다른 세포가 스크롤 것을 보여하지만 도시는 동일하게 유지 : 여기

는 스크린 샷입니다 내가 몇 년 전 비슷한 일이 한

enter image description here

답변

1

나는 우아한 해결책을 찾고 싶습니다. 지금은 표시 하위보기 오프셋을 추적하고 모양을 구성하여 수행 할 것입니다.

sample project에서 결과를 확인하십시오.

의 ViewController :

미래 참고로 나는 아래의 코드를 첨부 할 수 있습니다.m

// 
// OSViewController.m 
// ScrollMasks 
// 
// Created by #%$^Q& on 11/30/12. 
// Copyright (c) 2012 Demo. All rights reserved. 
// 

#import "OSViewController.h" 

@interface OSViewController() 

// subviews 
@property (strong) IBOutlet UIScrollView * scrollView; 

// all the subviews 
@property (strong) NSArray * maskedSubviews; 
// subviews visible at scrollview, we'll update only them 
@property (strong) NSArray * visibleMaskedSubviews; 

// updates the views from visibleMaskedSubviews 
-(void) updateVisibleSubviews; 
// updates the visibleMaskedSubviews array with the given scrollView offset 
-(void) updateVisibleSubviewsArrayForOffset:(CGPoint) offset; 
@end 

@implementation OSViewController 

-(void) unused {} 

#pragma mark - view 

-(void) viewWillAppear:(BOOL)animated { 
    [self updateVisibleSubviews]; 
    [super viewWillAppear:animated]; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    /* 
    See -updateVisibleSubviews comment for the class comments 
    */ 
    UIView * newMaskedView = nil; 
    NSMutableArray * newMaskedSubviews = [NSMutableArray array]; 

    const CGSize scrollViewSize = self.scrollView.bounds.size; 
    const int totalSubviews = 10; 
    const float offset = 20.; 
    const float height = 100.; 

    UIImage * maskImage = [UIImage imageNamed:@"PeeringFrog.jpg"]; 

    /* 

    // Uncomment to compare 

    UIImageView * iv = [[UIImageView alloc] initWithFrame:self.scrollView.bounds]; 
    iv.image = maskImage; 
    [self.view insertSubview:iv atIndex:0]; 
    */ 

    // add scrollview subviews 
    for (int i = 0; i < totalSubviews; i++) { 

     CGRect newViewFrame = CGRectMake(offset, offset*(i+1) + height*i, scrollViewSize.width - offset*2, height); 
     newMaskedView = [UIView new]; 
     newMaskedView.frame = newViewFrame; 
     newMaskedView.clipsToBounds = YES; 
     newMaskedView.backgroundColor = [UIColor redColor]; 
     newMaskedView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth; 

     UIImageView * maskImageView = [UIImageView new]; 
     maskImageView.frame = CGRectMake(0, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height); 
     maskImageView.image = maskImage; 
     [newMaskedView addSubview:maskImageView]; 

     [self.scrollView addSubview:newMaskedView]; 
     [newMaskedSubviews addObject:newMaskedView]; 
    } 

    self.scrollView.contentSize = CGSizeMake(scrollViewSize.width, (height+offset)*totalSubviews + offset*2); 

    self.maskedSubviews = [NSArray arrayWithArray:newMaskedSubviews]; 
    [self updateVisibleSubviewsArrayForOffset:self.scrollView.contentOffset]; 
} 

-(void) updateVisibleSubviews { 
    [self updateVisibleSubviewsArrayForOffset:self.scrollView.contentOffset]; 

    for (UIView * view in self.visibleMaskedSubviews) { 

     /* 
     TODO: 
     view must be UIView subclass with the imageView initializer and imageView frame update method 
     */ 

     CGPoint viewOffset = [self.view convertPoint:CGPointZero fromView:view]; 
     UIImageView * subview = [[view subviews] objectAtIndex:0]; 
     CGRect subviewFrame = subview.frame; 
     subviewFrame = CGRectMake(-viewOffset.x, -viewOffset.y, subviewFrame.size.width, subviewFrame.size.height); 
     subview.frame = subviewFrame; 
    } 
} 


#pragma mark - scrollview delegate & utilities 
-(void) scrollViewDidScroll:(UIScrollView *)scrollView { 
    [self updateVisibleSubviews]; 
} 

-(void) updateVisibleSubviewsArrayForOffset:(CGPoint) offset { 

    NSMutableArray * newVisibleMaskedSubviews = [NSMutableArray array]; 
    for (UIView * view in self.maskedSubviews) { 
     CGRect intersectionRect = CGRectIntersection(view.frame, self.scrollView.bounds); 
     if (NO == CGRectIsNull(intersectionRect)) { 
      [newVisibleMaskedSubviews addObject:view]; 
     } 
    } 

    self.visibleMaskedSubviews = [NSArray arrayWithArray:newVisibleMaskedSubviews]; 
} 

#pragma mark - memory 
- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

@end 

ViewController.h

// 
// OSViewController.h 
// ScrollMasks 
// 
// Created by #%$^Q& on 11/30/12. 
// Copyright (c) 2012 Demo. All rights reserved. 
// 

/* 
PeeringFrog image is taken (and resized) from Apple sample project "PhotoScroller" 
*/ 

#import <UIKit/UIKit.h> 

@interface OSViewController : UIViewController <UIScrollViewDelegate> 

@end 
+0

코드를 살펴 보는 과정에 있지만이 샘플 프로젝트는 내가 찾고있는 정확한 효과를 복제하는 것으로 보입니다. – SonnyBurnette

+0

@SonnyBurnette 그렇습니다. 레이어를 기반으로 한 아름다운 솔루션을 놓칠 수 있으므로 아직 대답을 받아들이지 않는 것이 좋습니다. 내 솔루션은 좋은 아닌 많은 논리가 필요한 scrollView 대리자를 기반으로합니다. –

+0

좋은 지적. 나는 수용을 들어 올리고 조금 후에 다시 방문 할 것이다. – SonnyBurnette

0

. 처음에는 CGImageMaskCreate를 사용해 보았지만 투명 "컷 아웃"이있는 이미지를 만든 다음 애니메이션 효과를 사용하여 이미지 아래로 스크롤했습니다.

귀하의 경우 린넨 이미지가 화면 크기에 해당됩니다. 그런 다음 이미지 편집기 (저는 김프를 사용합니다)를 사용하여 평면 색상을 사용하여 린넨에 상자 몇 개를 그립니다. 그런 다음 그 상자 색상을 투명하게 매핑하여 컷 아웃을 만듭니다. 이것을 할 수있는 다른 방법이 있지만 그것이 내가하는 방법입니다.

앱에서 두 개 이상의 이미지 뷰를 기본 뷰에 추가하십시오. 실행시 결정되므로 배치에 대해 걱정하지 마십시오. 이 이미지 뷰를 "스크롤"할 이미지가 포함되도록 설정해야합니다. 그런 다음 린넨이있는 UIImageView를 추가하여 맨 위에 올리면 전체 화면 크기를 차지합니다. 위쪽 UIImageView의 배경이 투명으로 설정되어 있는지 확인하십시오.

앱이 시작되면 "아래"이미지 뷰를 위에서 아래로 레이아웃 한 다음 "y"위치를 수정하여 아래 이미지 뷰를 스크롤하는 [UIView beginAnimation]을 시작하십시오. 이 애니메이션에는 상단 이미지보기가 화면에서 완전히 벗어난 경우 호출되는 완료 콜백이 있어야합니다. 그런 다음 완료 콜백에서 현재 상태를 레이아웃하고 애니메이션을 다시 시작합니다. 저는 여기에 사용되는 코드의 배짱이다 (그러나주의, 내 스크롤, 상단하지 바닥을 떠나 내 이미지가 모두 같은 크기였다 오른쪽이었다.)

- (void)doAnimationSet 
    { 

     [iv1 setFrame:CGRectMake(0, 0, imageWidth, imageHeight)]; 
     [iv2 setFrame:CGRectMake(imageWidth, 0, imageWidth, imageHeight)]; 
     [iv3 setFrame:CGRectMake(imageWidth*2, 0, imageWidth, imageHeight)]; 

     [self loadNextImageSet]; 

     [UIView beginAnimations:nil context:nil]; 
     [UIView setAnimationDuration:10]; 
     [UIView setAnimationCurve:UIViewAnimationCurveLinear]; 

     [iv1 setFrame:CGRectMake(-imageWidth, 0, imageWidth, imageHeight)]; 
     [iv2 setFrame:CGRectMake(0, 0, imageWidth, imageHeight)]; 
     [iv3 setFrame:CGRectMake(imageWidth, 0, imageWidth, imageHeight)]; 

     [UIView setAnimationDelegate:self]; 
     [UIView setAnimationDidStopSelector:@selector(doneAnimation:finished:context:)]; 

     [UIView commitAnimations]; 

    } 

    - (void)doneAnimation:(NSString *)aid finished:(BOOL)fin context:(void *)context 
    { 
     [self doAnimationSet]; 
    } 

이것은 당신에게 당신이 찾고있는 효과를 제공한다 에 대한. 행운을 빌어 요.

+0

무한 수평 스크롤 제스처 수행인가요? –

+0

@ A-Live, 아니 제스처에 의해 구동되지 않습니다. –

+0

이 스 니펫이 scrollView 대리인과 함께 작동하는 것을 상상할 수 없습니다. 더 잘 설명해 주시겠습니까? –