Android: Как получить пользовательский вид, чтобы частично перерисовать?

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

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

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

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

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

Ответы

Ответ 1

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

 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);
     }
 }

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

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

Ответ 2

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

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

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