Как мне представить UIViewController путем масштабирования? - PullRequest
9 голосов
/ 07 октября 2011

В моем приложении для iPad у меня есть контроллер представления с небольшим представлением таблицы. Когда вы нажимаете на табличное представление, он открывает модальный контроллер представления, который является более крупной и более совершенной версией маленького табличного представления. Я хотел бы создать анимацию из предварительно отрендеренного изображения контроллера большого представления, уменьшив размер изображения до размера представления маленькой таблицы и увеличив его до полного размера экрана, а затем заменив изображение на «реальный» вид контроллер. * * +1001

Что-то вроде:

LargeViewController* lvc = [[LargeViewController alloc] init];
[self presentModalViewController:lvc byZoomingFromRect:CGRectMake(50,50,200,300)];

Я знаю, что вы можете создать изображение из вида:

- (UIImage *) imageWithView:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, [[UIScreen mainScreen] scale]); 
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

Но как сделать так, чтобы контроллер вида рисовал сам (за кадром), чтобы я мог использовать его вид и масштабировать изображение в анимации для заполнения экрана?

Заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 26 октября 2011

Полагаю, вы хотите создать свою собственную анимацию. В прошлом месяце я играл с чем-то в этом роде. Моим решением было добавить пользовательский вид (возможно, взятый из контроллера представления) к текущему виду как наложение. Это работает и со слоями.

Сначала вы получаете Image из вашего «будущего» или «настоящего» контроллера представления, как вы делали в своем примере кода выше. Обычно содержимое контроллеров представления должно быть доступно при визуализации в контекст.

Теперь у вас есть изображение. Манипулирование изображением должно быть сделано вами.

Добавить изображение в UIImageView. Этот ImageView может быть добавлен как подпредставление или слой. Теперь у вас есть слой, где вы можете свободно рисовать над вашим фактическим пользовательским интерфейсом. Иногда вам нужно переместить слой или вид вокруг, чтобы он идеально перекрывал ваш вид. Это зависит от вашей настройки просмотра. Если вы имеете дело с Tableviews, добавить подпредставление не так просто. Так что лучше используйте слой.

После того, как вся работа была выполнена, представьте новый контроллер представления без анимации, чтобы он сразу появился.

Удалите слой или вид из родительского вида после выполнения работы и очистите.

Это звучит сложно, но как только вы это сделаете, у вас есть шаблон для этого. В «WWDC 2011, Сессия 309 Представление раскадровки интерфейса» Apple представила «пользовательские сегменты», в которых вы найдете механизм для именно того, что вы хотите сделать. Приведенный ниже код вырезан из более старого проекта, он немного грязный и должен быть очищен. Но для демонстрации принципа это должно сработать:

-(void) animate {

      static LargeViewController* lvc = [[LargeViewController alloc] init];

      UIGraphicsBeginImageContextWithOptions(self.bounds.size, view.opaque, [[UIScreen mainScreen] scale]); 
     [lvc.view.layer renderInContext:UIGraphicsGetCurrentContext()];

      // Create a ImageView to display your "zoomed" image
      static UIImageView* displayView = [[UIImageView alloc] initWithFrame:self.view.frame];
      static UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
      UIGraphicsEndImageContext();

      // Add your image to the view
      displayView.image = img;

      // insert the view above your actual view, adjust coordinates in the
      // frame property of displayView if overlay is misaligned
      [[self.view] addSubview:displayView];

      // alternatively you can use the layer
      // [self.view.layer addSublayer:displayView.layer];

      // draw the imageView
      [displayView setNeedsDisplay];

      // do something in background. You may create your own
      // construction, i.e. using a timer
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

          NSDate *now = [NSDate date];
          NSTimeInterval animationDuration = 3.;
          NSTimeInterval t = -[now timeIntervalSinceNow];
          while (t < animationDuration) {

              t = -[now timeIntervalSinceNow];

              // Do some animation here, by manipulation the image
              // or the displayView

              // <calculate animation>, do something with img
              // you have exact timing information in t,
              // so you can set the scalefactor derived from t
              // You must not use an UIImage view. You can create your own view
              // and do sth. in draw rect. Do whatever you want,
              // the results will appear
              // in the view if you added a subview
              // or in a layer if you are using the layer

              dispatch_sync(dispatch_get_main_queue(), ^{

                  // display the result
                  displayView.image = img;
                  [displayView setNeedsDisplay];
              });
          }
       });

      // now the animation is done, present the real view controller
      [self presentModalViewController:lvc animated:NO];

      // and clean up here
}
0 голосов
/ 08 октября 2011

UIKit позаботится обо всем этом для вас. Хотя решение jbat100 может быть выполнено и для работы, вы можете сделать это, просто установив начальный кадр lvc на меньший прямоугольник, с которого вы хотите начать, а затем, когда вы установите слишком полный кадр, Неявная анимация для смены кадра будет обрабатывать анимацию масштабирования для вас. Каждый UIView имеет CALayer, в котором рисуется его содержимое, и этот слой имеет несколько неявных настроек анимации для анимированных изменений определенных свойств, таких как свойства фрейма или положения. Вот мой непроверенный удар:

       .
       .
   lvc.view.frame = CGRectMake(50,50,200,300);
   [self performSelector:@selector(setFrameToFullScreen) withObject:nil afterDelay:0];

}

- (void)setFrameToFullScreen {
   lcv.view.frame = [UIScreen mainScreen].bounds;
}

Вызов performSelector:withObject:afterDelay вызовет вызов setFrameToFullScreen в следующем цикле цикла выполнения. Если вы не сделаете что-то подобное, то будет использоваться только последний кадр, и система не распознает изменение в кадре и не применяет его неявную анимацию к слою представлений.

0 голосов
/ 07 октября 2011

Возможно, вы могли бы использовать что-то вроде

CGAffineTransform tr = CGAffineTransformScale(lvc.view.transform, 0.5, 0.5);

, чтобы встроить уменьшенную версию представления в ваш родительский контроллер представления, затем представить lvc модально и восстановить масштаб, когда пользователь нажимает на представление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...