모바일 사파리 탭과 같은 UIScrollView 수평 페이징
모바일 Safari에서는 하단에 페이지 컨트롤이있는 고유 한 UIScrollView 수평 페이징 뷰를 입력하여 페이지를 전환 할 수 있습니다.
가로로 스크롤 가능한 UIScrollView가 다음보기의 콘텐츠 중 일부를 표시하는 특정 동작을 복제합니다.
Apple에서 제공하는 한 예제 : PageControl은 가로 페이징에 UIScrollView를 사용하는 방법을 보여 주지만 모든보기는 전체 화면 너비를 차지합니다.
모바일 Safari처럼 다음보기의 일부 콘텐츠를 표시하는 UIScrollView를 얻으려면 어떻게해야합니까?
UIScrollView
페이징이 활성화 된 A 는 프레임 너비 (또는 높이)의 배수에서 중지됩니다. 따라서 첫 번째 단계는 페이지의 너비를 제공하는 것입니다. 너비를 UIScrollView
. 그런 다음 서브 뷰의 크기를 원하는만큼 크게 설정하고 UIScrollView
의 폭의 배수를 기반으로 중앙을 설정합니다 .
그런 다음, 사용자가 설정 물론 다른 페이지,보고 싶은대로 이후 clipsToBounds
에 NO
mhjoy가 있습니다. 트릭 부분은 사용자가 UIScrollView
의 프레임 범위 밖에서 드래그를 시작할 때 스크롤하는 것 입니다. 내 솔루션 (최근 에이 작업을 수행해야했을 때)은 다음과 가변합니다.
크리에이트 UIView
클래스 서브 (즉 포함 ClipView
) UIScrollView
과의 파단. 본질적으로, 당신이 그것은 UIScrollView
정상적인 상황에서 가질 것이라고 가정하는 틀을 가져야합니다 . 장소 UIScrollView
의 중심에 ClipView
. 가 부모보기 너비의 너비보다 작 으면 ClipView
의 clipsToBounds
가로 설정되어 있는지 확인하십시오 YES
. 또한에 ClipView
대한 참조가 필요합니다 UIScrollView
.
-step는 무시 마지막하는을 구석으로입니다 - (UIView *)hitTest:withEvent:
내부 ClipView
.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
return [self pointInside:point withEvent:event] ? scrollView : nil;
}
이것은 기본적으로 터치 영역을 UIScrollView
부모 뷰의 프레임으로 확장 합니다. 정확히 필요한 것입니다.
다른 옵션은 또 메서드 를 하위 클래스 화 UIScrollView
하고 재정의하는 - (BOOL)pointInside:(CGPoint) point withEvent:(UIEvent *) event
것이지만 클리핑을 수행하려면 컨테이너 뷰가 여전히 필요하며 의-frame YES
만을 기준 으로 반환 할시 기를 결정하기 어려울 수 있습니다 UIScrollView
.
참고 : 하위보기 사용자 상호 작용에 문제가있는 경우 Juri Pakaste의 hitTest : withEvent : 수정 도보고 봐야 합니다.
ClipView
위 의 솔루션은 저에게도 다른 -[UIView hitTest:withEvent:]
구현 을 수행해야했습니다 . Ed Marty의 버전은 수평 스크롤 뷰 내부에있는 수직 스크롤 뷰로 작업하는 사용자 상호 작용을 수평 스크롤합니다.
다음 버전이 저에게 맞는다.
-(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
UIView* child = nil;
if ((child = [super hitTest:point withEvent:event]) == self)
return self.scrollView;
return child;
}
scrollView의 프레임 크기를 페이지 크기로 설정하십시오.
[self.view addSubview:scrollView];
[self.view addGestureRecognizer:mainScrollView.panGestureRecognizer];
이제에서 패닝 할 수 있으며 self.view
scrollView의 콘텐츠가 스크롤됩니다.
또한 scrollView.clipsToBounds = NO;
내용이 잘리지 않도록 사용 합니다.
사용자 지정 UIScrollView를 사용하는 것은 나에게 가장 빠르고 간단한 방법 이었기 때문입니다. 그러나 발송 된 코드를보고 메시지를 공유했습니다. 내 요구 사항은 콘텐츠가 작은 UIScrollView가 필요했기 때문에 UIScrollView 자체는 페이징 효과를 위해 작았습니다. 게시물에 나와있는 스 와이프 할 수 없습니다. 하지만 이제 할 수 있습니다.
CustomScrollView 클래스와 UIScrollView 하위 클래스를 만듭니다. 그런 다음 .m 파일에 다음을 추가하기 만하면됩니다.
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
return (point.y >= 0 && point.y <= self.frame.size.height);
}
이를 통해 좌우 (수평)로 스크롤 할 수 있습니다. 그에 따라 경계를 조정하여 스 와이프 / 스크롤 터치 영역을 설정합니다. 즐겨!
자동으로 scrollview를 반환 할 수있는 다른 구현을 만들었습니다. 따라서 프로젝트에서 재사용을 제한하는 IBOutlet이 필요하지 않습니다.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
if ([self pointInside:point withEvent:event]) {
for (id view in [self subviews]) {
if ([view isKindOfClass:[UIScrollView class]]) {
return view;
}
}
}
return nil;
}
ClipView hitTest 구현에 대해 잠재적으로 유용한 또 다른 수정이 있습니다. ClipView에 대한 UIScrollView 참조를 제공 할 필요가 없었습니다. 아래 구현에서는 ClipView 클래스를 재사용하여 모든 항목의 히트 테스트 영역을 확장 할 수 있으며 참조를 제공 할 필요가 없습니다.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
if (([self pointInside:point withEvent:event]) && (self.subviews.count >= 1))
{
// An extended-hit view should only have one sub-view, or make sure the
// first subview is the one you want to expand the hit test for.
return [self.subviews objectAtIndex:0];
}
return nil;
}
위의 upvoted 제안을 구현했지만 UICollectionView
프레임 밖의 모든 것을 화면에서 벗어나는 것으로 간주했습니다. 이로 인해 사용자가 해당 셀을 향해 스크롤 할 때 주변 셀이 경계를 벗어난 상태로만 렌더링되었으며 이는 이상적이지 않았습니다.
내가 한 일은 아래의 메소드를 델리게이트 (또는 UICollectionViewLayout
) 에 추가하여 스크롤 뷰의 동작을 에뮬레이션하는 것 입니다.
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
if (velocity.x > 0) {
proposedContentOffset.x = ceilf(self.collectionView.contentOffset.x / pageSize) * pageSize;
}
else {
proposedContentOffset.x = floorf(self.collectionView.contentOffset.x / pageSize) * pageSize;
}
return proposedContentOffset;
}
이렇게하면 스 와이프 동작의 위임을 완전히 피할 수 있으며 이는 보너스이기도합니다. 는 UIScrollViewDelegate
라는 유사한 방법이 scrollViewWillEndDragging:withVelocity:targetContentOffset:
페이지 UITableViews 및 UIScrollViews에 사용될 수있다.
이 SO 질문의 기술을 지원하면서 스크롤보기의 하위보기에서 탭 이벤트 실행을 활성화합니다. 가독성을 위해 스크롤 뷰 (self.scrollView)에 대한 참조를 사용합니다.
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *hitView = nil;
NSArray *childViews = [self.scrollView subviews];
for (NSUInteger i = 0; i < childViews.count; i++) {
CGRect childFrame = [[childViews objectAtIndex:i] frame];
CGRect scrollFrame = self.scrollView.frame;
CGPoint contentOffset = self.scrollView.contentOffset;
if (childFrame.origin.x + scrollFrame.origin.x < point.x + contentOffset.x &&
point.x + contentOffset.x < childFrame.origin.x + scrollFrame.origin.x + childFrame.size.width &&
childFrame.origin.y + scrollFrame.origin.y < point.y + contentOffset.y &&
point.y + contentOffset.y < childFrame.origin.y + scrollFrame.origin.y + childFrame.size.height
){
hitView = [childViews objectAtIndex:i];
return hitView;
}
}
hitView = [super hitTest:point withEvent:event];
if (hitView == self)
return self.scrollView;
return hitView;
}
터치 이벤트를 캡처하려면이를 자녀보기에 추가하십시오.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
(이것은 user1856273의 솔루션의 변형입니다. 가독성을 위해 정리하고 Bartserk의 버그 수정을 통합했습니다. user1856273의 답변을 편집하려고 생각했지만 변경하기에는 너무 컸습니다.)
내 버전 스크롤에있는 버튼을 누르면-작업 =)
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView* child = nil;
for (int i=0; i<[[[[self subviews] objectAtIndex:0] subviews] count];i++) {
CGRect myframe =[[[[[self subviews] objectAtIndex:0] subviews]objectAtIndex:i] frame];
CGRect myframeS =[[[self subviews] objectAtIndex:0] frame];
CGPoint myscroll =[[[self subviews] objectAtIndex:0] contentOffset];
if (myframe.origin.x < point.x && point.x < myframe.origin.x+myframe.size.width &&
myframe.origin.y+myframeS.origin.y < point.y+myscroll.y && point.y+myscroll.y < myframe.origin.y+myframeS.origin.y +myframe.size.height){
child = [[[[self subviews] objectAtIndex:0] subviews]objectAtIndex:i];
return child;
}
}
child = [super hitTest:point withEvent:event];
if (child == self)
return [[self subviews] objectAtIndex:0];
return child;
}
그러나 [[self subviews] objectAtIndex : 0] 만 스크롤이어야합니다.
다음은 Ed Marty의 답변을 기반으로 한 Swift 답변이지만 스크롤 뷰 내에서 버튼 탭 등을 허용하는 Juri Pakaste의 수정도 포함됩니다.
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let view = super.hitTest(point, with: event)
return view == self ? scrollView : view
}
참고 URL : https://stackoverflow.com/questions/1220354/uiscrollview-horizontal-paging-like-mobile-safari-tabs
'IT' 카테고리의 다른 글
Eclipse에서 AVD 또는 SDK 관리자를 사용할 수 없습니다. (0) | 2020.09.08 |
---|---|
Ruby on Rails : rake db : migrate 마이그레이션을 되돌리려면 어떻게해야합니까? (0) | 2020.09.08 |
SQL Server에서 bigint (UNIX 타임 스탬프)를 datetime으로 변환해야합니까? (0) | 2020.09.08 |
mongodb에 강력하지 않습니다. errno : 61 연결이 거부되었습니다. (0) | 2020.09.08 |
C / C ++에서 log base (2)를 작성하는 방법 (0) | 2020.09.08 |