더 작은 경우 UIScrollView의 컨텐츠 중심
확대 / 축소 및 스크롤에 사용 하는 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)];
}
매우 간단한 해결책이 있습니다! ScrollViewDelegate를 확대하면서 하위보기의 중앙 (이미지보기)을 업데이트하기 만하면됩니다. 확대 / 축소 된 이미지가 스크롤보기보다 작 으면 subview.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);
}
@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 = UIEdgeInsetsMake(offsetY, offsetX, 0, 0)
}
좋아, 나는 지난 이틀 동안이 싸움을하고 마침내 마침내 믿을만한 (지금까지 ...) 해결책을 찾았으며 그것을 공유하고 다른 사람들에게 약간의 고통을 구해야한다고 생각했습니다. :)이 솔루션에 문제가 있으면 소리 치십시오!
기본적으로 StackOverflow, Apple 개발자 포럼 검색, three20, ScrollingMadness, ScrollTestSuite 등의 코드를 살펴 보았습니다. UIScrollView의 오프셋 및 / 또는 삽입과 함께 UIImageView 프레임을 확대하려고했습니다. ViewController 등에서 아무 효과가 없었습니다 (다른 사람들도 알았 듯이).
그것에 자고 난 후, 나는 몇 가지 대안 각도를 시도했다.
- UIImageView를 서브 클래스 화하여 자체 크기를 동적으로 변경합니다. 이는 전혀 효과가 없었습니다.
- UIScrollView를 서브 클래스 화하여 자체 contentOffset을 동적으로 변경합니다. 이것이 나에게 승자 인 것 같습니다.
이 서브 클래 싱 UIScrollView 메서드를 사용하면 contentOffset 뮤 테이터를 재정 의하여 이미지가 뷰포트보다 작게 조정될 때 {0,0}으로 설정되지 않습니다. 대신 이미지가 뷰포트의 중앙에 유지되도록 오프셋을 설정합니다. 지금까지는 항상 작동하는 것 같습니다. 넓고, 크고, 작고 큰 이미지로 확인했으며 "작동하지만 최소 확대 / 축소로 핀치가 끊어집니다"문제가 없습니다.
이 솔루션을 사용하는 예제 프로젝트를 github에 업로드했습니다. http://github.com/nyoron/NYOBetterZoom
이 코드는 대부분의 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;
}
자동 레이아웃을 사용하는 스크롤보기에 더 적합한 솔루션을 보려면 스크롤보기 하위보기의 프레임을 업데이트하는 대신 스크롤보기의 내용 삽입을 사용하십시오.
- (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);
}
현재 나는에 기반하여 오프셋을 조정하기 위해 서브 클래스 화 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 데모 에서 실제로 작동하는 것을 볼 수 있습니다 .
나는이 문제와 싸우는 데 하루를 보냈고 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 메소드이므로 빌드 문제가 발생하지 않도록 뷰 컨트롤러의 선언에 추가하는 것을 잊지 마십시오.
애플은 2010 WWDC 세션 비디오를 아이폰 개발자 프로그램의 모든 멤버들에게 공개했다. 논의 된 주제 중 하나는 사진 앱을 만드는 방법입니다 !!! 그들은 매우 유사한 앱을 단계별로 구축하고 모든 코드를 무료로 제공했습니다.
개인 API도 사용하지 않습니다. 비공개 계약으로 인해 여기에 코드를 넣을 수는 없지만 여기에 샘플 코드 다운로드 링크가 있습니다. 액세스하려면 로그인해야 할 것입니다.
다음은 iTunes WWDC 페이지에 대한 링크입니다.
좋아,이 솔루션은 나를 위해 일하고있다. 나는 그것이 표시 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);
}
나는 항상 이미지의 UIScrollView크기를 조정했습니다. UIScrollView있는 ScrollView에서 또한 내가 만든 사용자 지정 클래스입니다.
-(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;
}
이 두 가지 방법으로 사진 앱처럼 동작하는 뷰를 가질 수 있습니다.
contentSizeUIScrollView 의 속성을 보고 (키-값 관찰 등을 사용하여) 스크롤보기의 크기보다 작을 contentInset때마다 자동으로 조정합니다 contentSize.
내용을 집중시키는 하나의 우아한 방법 UISCrollView은 이것입니다.
의 contentSize 에 하나의 관찰자를 추가 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 자체가 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 자체의 크기를 조정하기위한 적절한 반응), 비교적 쉽게 고칠 수 있습니다.
Erdemus가 게시 한 솔루션은 작동하지만… scrollViewDidZoom 메소드가 호출되지 않고 이미지가 왼쪽 상단에 붙어있는 경우가 있습니다. 간단한 해결책은 다음과 같이 이미지를 처음 표시 할 때 메소드를 명시 적으로 호출하는 것입니다.
[self scrollViewDidZoom: scrollView];
대부분의 경우이 방법을 두 번 호출 할 수도 있지만이 항목의 다른 답변보다 더 확실한 솔루션입니다.
Apple의 사진 스크롤러 예제는 원하는 것을 정확하게 수행합니다. 이것을 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;
}
내가 한 방법은 계층 구조에 추가 뷰를 추가하는 것입니다.
UIScrollView -> UIView -> UIImageView
당신 부여 UIView하여 같은 화면 비율을 UIScrollView, 그리고 중앙 UIImageView에 그.
애니메이션 흐름을 좋게 만들려면
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);
}];
}
이로 인해 튀는 효과가 발생하지만 미리 갑작스런 움직임은 포함되지 않습니다.
승인 된 답변 만 신속하지만 대리자를 사용하여 하위 클래스를 만들지 않습니다.
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)
}
내부 imageView의 초기 특정 너비 (예 : 300)가 있고 너비를 초기 너비보다 작은 줌 에서만 중앙에 맞추려는 경우 에도 도움이 될 수 있습니다.
func scrollViewDidZoom(scrollView: UIScrollView){
if imageView.frame.size.width < 300{
imageView.center.x = self.view.frame.width/2
}
}
위의 답변이 옳다는 것을 알고 있지만 설명과 함께 답변을 드리고 싶습니다. 의견을 통해 왜 우리가 이것을 좋아하는지 이해할 수 있습니다.
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)
}
이 작업을 수행하는 현재 방법은 다음과 같습니다. 더 좋지만 여전히 완벽하지는 않습니다. 설정을 시도하십시오.
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);
질문이 조금 오래되었지만 문제는 여전히 존재합니다. I는 그것을 해결 엑스 코드 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()
}
}
참고 URL : https://stackoverflow.com/questions/1316451/center-content-of-uiscrollview-when-smaller
'IT' 카테고리의 다른 글
| 트위터 부트 스트랩 드롭 다운이 화면 밖으로 나갑니다. (0) | 2020.06.24 |
|---|---|
| java.lang.NullPointerException : null 객체 참조에서 가상 메소드 'int android.view.View.getImportantForAccessibility ()'를 호출하려고 시도했습니다. (0) | 2020.06.24 |
| 문자열을 QString으로 변경하는 방법은 무엇입니까? (0) | 2020.06.24 |
| 파이썬에서 열거 형에 대한 일반적인 관행은 무엇입니까? (0) | 2020.06.24 |
| “com.google.firebase.provider.FirebaseInitProvider”클래스를 찾지 못했습니까? (0) | 2020.06.24 |