Можно ли сосредоточиться на контенте в приложении uiscrollview, как Apple Photos?
-
19-09-2019 - |
Вопрос
Я боролся с этой проблемой в течение некоторого времени, и, похоже, нет четкого ответа. Пожалуйста, дайте мне знать, если кто -нибудь выяснил это.
Я хочу показать фото в UIScrollView
это сосредоточено на экране (изображение может быть в портретной или ландшафтной ориентации).
Я хочу иметь возможность увеличить и пятно изображения только к краю изображения, как в приложении Photo.
Я попытался изменить contentInset
в viewDidEndZooming
Метод и этот вид справляются, но есть несколько сбоев.
Я также пытался сделать imageView
тот же размер, что и scrollView
и сосредоточить изображение там. Проблема в том, что когда вы увеличиваете масштаб, вы можете прокрутить весь imageView
и часть изображения может прокрутить вид.
Я нашел здесь похожий пост и дал лучший обходной путь, но не было найдено реального ответа:
Решение 3
Вот лучшее решение, которое я мог бы придумать для этой проблемы. Хитрость заключается в том, чтобы постоянно перенастроить кадр ImageView. Я считаю, что это работает намного лучше, чем постоянно настройка контент -энзионов или 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];
}
Вот как я рассчитываю шкалу масштабирования MIN в методе 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];
Другие советы
Один элегантный способ сосредоточиться на содержании UISCrollView
это.
Добавить одного наблюдателя в Содержание вашей 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
.
Этот код должен работать над большинством версий iOS (и был протестирован для работы на 3,1 вверх).
Он основан на коде Apple WWDC для приложения PhotoScroll.
Добавьте приведенное ниже в подкласс 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;
}