2014-09-25 5 views
0

У меня возникла следующая проблема.Пользовательский UIView drawRect вызывается даже с UIViewContentModeScaleAspectFill

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

public override void Draw(RectangleF rect) 
    { 
     base.Draw(rect); 
     CGContext context = UIGraphics.GetCurrentContext(); 
     if (Image != null) 
     { 
      var imageRect = getAspectFillRect(rect, Image.Size); 
      context.DrawImage(imageRect, Image.CGImage); 
     } 
     else 
     { 
      this.BackgroundColor.SetFill(); 
      context.FillRect(this.Bounds); 
     } 
    } 

Этот код просто рисует изображение, установленное в Image собственности таким образом, который имитирует аспект UIImageView»Наполним вариант вычисляя rect, который отобразит изображение в режиме заполнения аспект с использованием этой строки кода getAspectFillRect(rect, Image.Size);

У меня также есть UICollectionView с пользовательскими макетами и пользовательскими ячейками. Каждый пользовательский интерфейс UICollectionViewCell определяется в файле xib, там у меня есть все необходимые ограничения, и я там также имею свое собственное представление для отображения изображений. Для этой точки зрения в построителе интерфейса я установил режим содержимого в «Аспект заполнения». Пользовательский UICollectionViewLayout выполнен таким образом, что ячейка расширяется (вы увидите пример в ближайшее время). Таким образом, изображение внутри ячейки также должно масштабироваться, и поскольку я установил параметр «Аспект заполнения», он не должен вызывать drawRect моего пользовательского представления, а должен просто масштабировать уже нарисованное содержимое. Но это не тот случай!

LOOK HERE, чтобы увидеть видео, которое демонстрирует, что происходит. Вы можете видеть, что изображение внутри не растет вместе с ячейкой. Проблема в том, что до того, как начнется анимация с расширением ячейки, начинается drawRect моего настраиваемого UIView с прямоугольником, который в конечном итоге будет установлен после анимации. Поэтому я получаю отрывистую анимацию. В моем специальном коде макета я просто вызываю LayoutIfNeeded после обновления ограничений ячейки. Я не звоню setNeedsDisplay, поэтому я не понимаю, почему вызван мой drawRect.

Для эксперимента я заменил свой собственный образ изображения на UIImageView, я установил его в режиме контента «Аспект заполнения» и LOOK HERE, что произошло. ДА! Это сработало. Поэтому я предполагаю, что проблема не в настраиваемом макете UICollectionView, а в моем собственном классе рисования изображений.

Что я должен учитывать? Как я должен справиться с этим делом? Есть идеи? Спасибо!

ответ

0

DrawRect будет называться всякий раз, когда система «чувствует» ее должна называть это. Независимо, если вы звоните SetNeedsDisplay или нет.

Теперь, установив ContentMode в ScaleAspectFill не означает, что DrawRect будет не назвать. На самом деле, от компании Apple документы here:

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

Это означает, что, если вы не хотите проходить чрезмерное рисование содержимого самостоятельно, просто установите свойство ContentMode. В вашем примере вы :, используя DrawRect, чтобы нарисовать.

Теперь, тот факт, что DrawRect называются перед стартами анимации, но с целевым значением для Bounds (или Frame?) Означает, что целевое значение этих свойств устанавливаются перед изменением отделки. Во время анимации эти свойства не изменяются. Примечание во время. Значение Bounds 'или Frame не изменится по всем значениям текущего перехода. Он знает только «начало» и «конец».

Что произойдет в вашем приложении, если DrawRect был не, вызванный перед началом анимации, но был вызван после окончания анимации? Ну, ячейка изменила бы размер вместе с ее подвью, но ваше изображение будет оставаться небольшим во всей анимации и привязаться к большому размеру после завершения анимации. Так это так или иначе.

Решения:

  • Использование в UIImageView.
  • Если вам нужно использовать пользовательский вид, используйте UIImageView для отображения вашего изображения.
  • Нарисуйте свое изображение на пользовательском CALayer и добавьте этот слой на слой пользовательского вида.
+0

Hello Dimitris. Спасибо за ответ. Я также собирался сделать все и установить в качестве образа UIImageView. Но для меня это было не лучшее решение. Использование UIImageView в моем случае не является решением. Третье решение, я думаю, такое же, как и мое, не так ли? Я думаю, что это снова будет работать, как в моем случае с резкой анимацией. Я думал, что если UIImageView работает, тогда должен быть способ построить класс, который будет работать как UIImageView в этом текущем случае. что ты думаешь? – kyurkchyan

+0

Нет, вариант №3 будет работать. Выполнение этого слоя - это то, что делает UIImageView. Не нужно создавать собственное изображение. Однако для его корректировки потребуется некоторая работа с анимацией UICollectionView. Начните с простого примера: нарисуйте изображение на CALayer и измените его размер с помощью CABasicAnimation и посмотрите, что произойдет. Помните, вы должны думать с учетом «начала» и «конца». –

Смежные вопросы