2010-06-01 4 views
14

У меня есть пользовательский вид, который заполняет весь экран. (Клавиатура пианино) Когда пользователь прикасается к ключу, он вызывает вызов invalidate(), и вся клавиатура перерисовывается, чтобы показать новое состояние с помощью косвенного ключа.Android: Как получить пользовательский вид, чтобы частично перерисовать?

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

Итак, я подумал, давайте посмотрим на частичную перерисовку. Теперь я звоню invalidate(Rect dirty) с правильной грязной областью. Я установил свой метод onDraw(Canvas canvas) только для рисования ключей в грязной области, если я действительно хочу частично перерисовать. Это приводит к тому, что эти клавиши нарисованы, но остальная клавиатура полностью черная/не нарисована вообще.

Я ошибаюсь в ожидании, что вызов invalidate(Rect dirty) будет «кэшировать» текущий canvas, и только «разрешает» рисование в грязном регионе?

Есть ли способ достичь того, чего я хочу? (Путь к «Кэш» холст и только перерисовывать грязную зону»

ответ

18

Текущий хороший обходной путь, чтобы вручную кэшировать полный холст растрового изображения:

private void onDraw(Canvas canvas) 
{ 
    if (!initialDrawingIsPerformed) 
    { 
      this.cachedBitmap = Bitmap.createBitmap(getWidth(), getHeight(), 
      Config.ARGB_8888); //Change to lower bitmap config if possible. 
      Canvas cacheCanvas = new Canvas(this.cachedBitmap); 
      doInitialDrawing(cacheCanvas); 
      canvas.drawBitmap(this.cachedBitmap, 0, 0, new Paint()); 
      initialDrawingIsPerformed = true; 
    } 
    else 
    { 
      canvas.drawBitmap(this.cachedBitmap, 0, 0, new Paint()); 
      doPartialRedraws(canvas); 
    } 
} 

Ofcourse, вам нужно хранить информацию о том, что нужно перерисовать и желательно не использовать новый Paint каждый раз, но это подробности.

Также обратите внимание: растровые изображения довольно тяжелы в использовании памяти вашего приложения. У меня произошли сбой при кэшировании вида, который использовался с скроллер и это было в 5 раз больше высоты устройства, так как оно использовало> память 10 МБ!

+1

Хмм, мне не нравится это solutnio, потому что причина, по которой его ключи частично нарисованы, состоит в том, что он должен сначала полностью рисовать свои кандавы. Поэтому вопрос заключается в том, почему его полотно не правильно рисовало. – 2012-11-08 18:55:01

+1

Мне нужно заметить, что теперь я понимаю, что когда вы вызываете 'invalidate' с грязным' rect', вы можете просто использовать свой обычный код чертежа, и он должен фактически выполнять операции рисования, которые находятся в грязном 'rect'. 'Canvas' отбрасывает операции, которые находятся за пределами' rect'. Тем не менее, это означает, что многое из вашего собственного кода все еще отображается, и в моих тестах с ускорением HW на нем было медленнее, чем просто просмотр представления полностью. – Peterdk

+1

Обратите внимание, что для рисования растровых изображений на холсте параметр paint может быть нулевым, например. 'canvas.drawBitmap (bitmap, 0, 0, null)'. – greg7gkb

5

Чтобы дополнить ответ Peterdk, вы можете сохранить свои операции на картинке вместо растрового изображения.

  • битовая карта сохранит все пиксели, как он сказал, что это может занять много памяти.
  • Изображение сохранит вызовы, как DrawRect, DrawLine и т.д.

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

+0

Ницца, заглянем в это! – Peterdk

+0

Извините. Будет ли вызываться запись 'Picture'' drawBitmap (bitmap) '? Наверное, нет, не так ли? – Yeung

+0

Обратите внимание, что воспроизведение изображения поддерживается только на программных холстах, поэтому вы не можете использовать аппаратные уровни для просмотров, которые используют это. – greg7gkb

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