Дайте пользователю выбор между исходной ценой и намного более высокой ценой. Необходимо будет найти некоторый способ связать кнопки с их соответствующими ценами - цветом, положением, возможно, "эмоциональная коннотация" кнопки - что-то трудное, чтобы программно определить, но которому только нужен пользователь для соединения кнопки с ценой. Легкий, интуитивный и стычка, свободная для пользователя, трудного и, что еще более важно, опасный для сценариста - особенно, если Вы варьируетесь метод ассоциации.
Вы можете следить за свойством contentSize
в UIScrollView (используя наблюдение за ключом и т.п.) и автоматически настраивать contentInset
всякий раз, когда contentSize
изменится и станет меньше размера прокрутки.
Я сделал это так, чтобы добавить дополнительное представление в иерархию:
UIScrollView -> UIView -> UIImageView
Дайте вашему UIView
такое же соотношение сторон, что и у вашего UIScrollView
и поместите в него свой UIImageView
.
Ладно, думаю, я нашел довольно хорошее решение этой проблемы. Уловка состоит в том, чтобы постоянно корректировать фрейм 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];
}
One elegant way to center the content of UISCrollView
is this.
Add one observer to the contentSize of your UIScrollView
, so this method will be called everytime the content change...
[myScrollView addObserver:delegate
forKeyPath:@"contentSize"
options:(NSKeyValueObservingOptionNew)
context:NULL];
Now on your observer method:
- (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 ); }
You should change the [pointer
viewWithTag:100]
. Replace by your
представление содержимого UIView
.
imageGallery
, указывающий на размер вашего окна. Это исправит центр содержимого каждый раз, когда его размер изменится.
ПРИМЕЧАНИЕ: Этот контент работает не очень хорошо, только если используются стандартные функции масштабирования UIScrollView
.
Вот текущий способ, которым я делаю это. Он лучше, но все же не совершенен. Попробуйте настроить:
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
}
Хорошо, это решение работает для меня. У меня есть подкласс 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
в просмотре прокрутки также является созданным мною пользовательским классом.
-(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;
}
С помощью этих двух методов я могу получить представление, которое ведет себя так же, как приложение "Фотографии".
Хорошо, я боролся с этим последние два дни и выходные, и, наконец, придя к довольно надежному (пока ...) решению, я подумал, что должен поделиться им и избавить других от боли. :) Если вы обнаружите проблему с этим решением, пожалуйста, кричите!
Я в основном прошел через то, что есть у всех: поискал в StackOverflow, форумах разработчиков Apple, просмотрел код для three20, ScrollingMadness, ScrollTestSuite и т.д. / или вставки из ViewController и т. д., но ничего не работало отлично (как и все остальные).
Выспавшись на нем, я попробовал несколько альтернативных ракурсов:
С помощью этого подкласса метода UIScrollView я переопределяю мутатор contentOffset, поэтому он не устанавливает {0,0}, когда изображение масштабируется меньше, чем область просмотра - вместо этого он устанавливает смещение таким образом, чтобы изображение оставалось центрированным в область просмотра. Пока вроде всегда работает. Я проверил это с широкими, высокими, крошечными и большими изображениями, и у меня нет проблемы «работает, но ущипнуть при минимальном увеличении не удается».
Я загрузил на github пример проекта, который использует это решение, вы можете найти его здесь: http://github.com/nyoron/NYOBetterZoom
У меня очень простое решение! Все, что вам нужно, это обновить центр вашего подпредставления (изображения) при масштабировании ScrollViewDelegate. Если увеличенное изображение меньше, чем scrollview, отрегулируйте subview. Center else 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);
}
Apple выпустила видеозаписи сессии WWDC 2010 для всех участников программы для разработчиков iphone. Одна из обсуждаемых тем - как они создали приложение "Фото"!!! Они создали очень похожее приложение шаг за шагом и предоставили весь код бесплатно.
Оно также не использует приватный api. Я не могу разместить код здесь из-за соглашения о неразглашении, но вот ссылка на загрузку примера кода. Вам, вероятно, придется войти в систему, чтобы получить доступ.
И, вот ссылка на страницу iTunes WWDC:
Этот код должен работать на большинстве версий 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;
}