#iphone #objective-c #cocoa-touch #uiimage
#iPhone #objective-c #cocoa-touch #uiimage
Вопрос:
Я думаю, что это очень простой вопрос, но я борюсь с этим.
У меня есть скриншот (UIImage), который я помещаю в UIView (в моем примере ниже он называется screenShotView). Я хочу избавиться от этого screenShotView, постепенно раскрывая, что находится за этим screenShotView. Прямо сейчас мой screenShotView СЖИМАЕТСЯ влево, но я бы хотел, чтобы его РАМКА становилась все меньше и меньше, пока screenShotView больше не будет виден (без сжатия).
Это мой код. Если бы я выполнил то же преобразование с помощью UITextView (вместо UIImage), оно работало бы именно так, как я хотел бы, чтобы оно вело себя (без преобразования).
Возможно, я не понимаю концепцию кадрирования пользовательских изображений?
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:10];
[screenShotView setFrame:CGRectMake(0, 0, 0, 480)];
[UIView commitAnimations];
И вот как это выглядит в середине анимации:
И вот как я хотел бы, чтобы это выглядело в середине анимации:
Это код, обновленный в соответствии с предложениями Codo (см. Ниже), в результате чего у меня больше нет анимации. Синий экран просто появляется при нажатии кнопки. Я предполагаю, что я делаю что-то не так с добавлением вложенных представлений — проблема, похоже, в том, что никакие вложенные представления не добавляются и поэтому не могут исчезнуть:
-(IBAction)showNextText
{
screenShotView = [[UIImageView alloc] initWithImage:[self screenshot]];
[screenShotView setFrame:CGRectMake(0, 0, 320, 480)];
[screenShotScrollView setFrame:CGRectMake(0, 0, 320, 480)];
[self.view addSubview:screenShotScrollView];
[screenShotScrollView addSubview:screenShotView];
screenShotScrollView.scrollEnabled = NO;
[self setUpNextText];
[self removeOldText];
}
-(void)setUpNextText
{
NSString* secondText = @"This is the second text shown if the user clicks next.";
textView.text = secondText;
textView.textColor = [UIColor redColor];
textView.backgroundColor = [UIColor blueColor];
}
-(IBAction)removeOldText{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:5];
[screenShotScrollView setFrame:CGRectMake(0,0,320,480)];
[UIView commitAnimations];
}
Комментарии:
1. Необходимый вам переход — это что-то вроде старых фильмов «Звездные войны»? Положение и размер двух экранов не меняются, просто один перекрывает другой на определенной строке и скрывает другой со временем. Правильно?
2. @Nick Weaver: Точно! Мне следовало подумать о «Звездных войнах». Это похоже на линию или занавес, который вы перемещаете влево. Экраны не перемещаются — меняется только то, что отображается на экранах. От 100% до 0% для изображения выше и от 0% до 100% для изображения ниже.
3. У меня есть сомнения, что такой переход может быть легко создан! Однако я посмотрю на это завтра. Вам следует рассмотреть несколько простых анимаций альфа-смешивания: выглядит красиво и создается в течение нескольких минут.
4. @Nick Weaver: Большое спасибо. Я знаю, что альфа-смешивание выглядит красиво, но поскольку я хочу иметь эффект перелистывания страниц, мне нужен такой переход. Я попробовал это с UIScrollView, как предложил Codo, но пока безуспешно. Еще раз спасибо за вашу помощь.
5. @n.evermind Вы действительно пробовали
UIView transitionFromView ...
и UIViewAnimationOptionTransitionFlipFromLeft? Или UIViewAnimationOptionTransitionCurlUp? Тоже красиво смотрится 🙂
Ответ №1:
Ответ на вопрос
На самом деле это очень просто: я создал пример приложения для запуска перехода star wars (просто называю его здесь). Для простоты я буду просто называть два вида FirstView и secondView. Показан FirstView (будет вашим скриншотом), а secondView будет скользить слева. Я поместил кнопку на каждый вид, чтобы анимировать переход, который является wirde к doTransition
. Важной частью является установка скольжения в свойствах view clipsToBounds = YES
и autoresizesSubviews = NO
. Вот и все. Я опубликую несколько скриншотов.
- (void)viewDidLoad
{
[super viewDidLoad];
secondView.frame = CGRectMake(0, 0, 0, 480);
secondView.clipsToBounds = YES;
secondView.autoresizesSubviews = NO;
[self.view addSubview:firstView];
[self.view addSubview:secondView];
}
- (IBAction)doTransition
{
[UIView animateWithDuration:1.0
animations:^{
self.secondView.frame = CGRectMake(0,
0,
320,
480);
}];
}
Исследование по page curl
Я провел некоторое исследование по эффекту поворота страницы / curl. В основном все это присутствует в iOS, без особых усилий вы можете создать эффект перелистывания страницы iBook, но для этого требуется доступ к частным методам и классам. Я по-прежнему призываю всех взглянуть на это, потому что это может когда-нибудь быть открыто.
-
Приложение Apple iBooks Dynamic Page Curl — Демонстрационное приложение Стивена Троутона-Смита
-
Leaves — Приложение с пользовательским скручиванием страницы от Тома Броу, опробовано, скомпилировано и выглядит красиво!
-
App Store -безопасные анимации скручивания страниц — Статья о приложении Tom Brow Leaves, которое было разветвлено (две страницы) автором Ole Begemann
-
Реализация скручивания страницы iBooks с использованием алгоритма конической деформации — С демонстрационным приложением macOS, очень профессиональным и продвинутым, хотя и не подходящим для быстрого снимка, но все же вдохновляющим. Скачайте приложение!
-
Анатомия скручивания страницы — математический подход
Комментарии:
1. Спасибо, Ник, но опять же, я думаю, что это не совсем то, что я пытался сделать (моя вина, я должен был сделать это немного яснее). Codo внес предложение о том, как ОБРЕЗАТЬ скриншот, но это все равно не сработает.
2. Полностью изменен ответ, ну, это не ответ на ваш вопрос, но все еще может быть интересным.
3. Спасибо, Ник, очень любезно с твоей стороны. Я могу посмотреть на многое. Также Hoha (выше) предоставила какое-то решение, которое мне нужно протестировать.
Ответ №2:
Я предполагаю, что вам нужно поместить свой вид сверху в UIScrollView. Затем вы устанавливаете размер содержимого таким же, как размер UIScrollView, и отключаете прокрутку.
Затем вы создаете свою оригинальную анимацию (setFrame) в UIScrollView.
По сути, затем вы используете UIScrollView для введения отдельной системы координат для внутреннего вида. Когда внешний вид (вид прокрутки) становится меньше, это не искажает внутренний вид, а обрезает его.
Комментарии:
1. звучит правильно, но я пытался реализовать это (см. Код выше), но это просто не работает. Я предполагаю, что я делаю что-то неправильно при попытке добавить все эти разные представления. Любые предложения были бы очень признательны. Спасибо!
2. Можете ли вы более конкретно объяснить, что означает «просто не работает»? Я вижу две потенциальные проблемы в вашем коде: согласно скриншотам, высота представлений должна быть не 480 пикселей, а примерно 200 пикселей. Вы должны установить свойство contentSize для вида прокрутки.
3. Извините, я имею в виду, что анимации больше нет вообще (нет сжатия) и что синий вид (первоначально на заднем плане) просто появляется, а другой белый вид (первоначально спереди) просто исчезает. Что касается высоты пикселей, я установил ее равной 200, чтобы я мог видеть кнопку. О свойстве contentSize — как мне это установить и зачем это необходимо? Извините, что доставляю вам столько хлопот, и спасибо за ваше терпение.
Ответ №3:
CGRect fillRect = self.view.bounds;
leftImageView.clipsToBounds = YES;
leftImageView.contentMode = UIViewContentModeTopLeft;
leftImageView.frame = fillRect;
rightImageView.clipsToBounds = YES;
rightImageView.contentMode = UIViewContentModeTopRight;
rightImageView.frame = CGRectMake(fillRect.size.width, 0, 0, fillRect.size.height);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:3];
leftImageView.frame = CGRectMake(0, 0, 0, fillRect.size.height);
rightImageView.frame = fillRect;
[UIView commitAnimations];
Ответ №4:
Анимируйте не frame
, а center
. Смотрите документацию здесь.
Кроме того, если вам нужна совместимость только с iOS 4, используйте -animateWithDuration:animations:
[UIView animateWithDuration:10
animations:^{ screenShotView.center = CGPointMake(x, y) } ];
Комментарии:
1. Большое спасибо, но как мне это сделать?
[screenShotView setCenter:CGRectMake(0, 0, 0, 480)];
?2.
center
является CGPoint только с двумя координатами; используйтеCGPointMake(x, y)
3. Вы также могли бы анимировать x-часть фрейма и сохранить ширину и высоту неизменными: как
CGRectMake(320, 0, 320, 480)
.4. @n.evermind Хорошо, возможно, я вас неправильно понимаю. Что вы подразумеваете под «становиться все меньше и меньше»?
5. @fabian798: Я обновил свой вопрос изображением того, как бы я хотел, чтобы оно отображалось. Вы предложили убрать все это из поля зрения.
Ответ №5:
Я не уверен, что полностью понимаю, как вы хотите, чтобы ваш вид исчез.
Если предполагается, что он будет становиться все более и более прозрачным, используйте следующий код (вместо setFrame):
[screenShotView setAlpha: 0.0f];
Если предполагается, что он будет становиться все меньше и меньше (но сохранит свой центр), то попробуйте:
[screenShotView setFrame:CGRectMake(screenShotView.frame.x, screenShotView.frame,y, 0, 0)];
Комментарии:
1. Спасибо за вашу помощь, но я думаю, что это не совсем то, что мне нужно. Я думаю, что я не очень четко выразился — я обновил свой пост изображением, которое иллюстрирует, чего я хотел бы достичь. Если бы вы могли быстро взглянуть, я был бы очень благодарен.