2010-05-04 1 views
7

Как я могу переопределить onDraw, чтобы взять то, что было бы нарисовано (как растровое изображение) и преобразовать его?Переопределить onDraw, чтобы изменить способ создания рисунка (Android)

Метод ниже работает, но, к сожалению, этот метод предполагает создание растрового изображения размером всего экрана - а не только области, на которую нарисовано. Если я использую это для рисования элементов пользовательского интерфейса, он перерисовывается для каждого элемента пользовательского интерфейса. Можно ли это сделать более эффективно?

@Override 
protected void onDraw(Canvas canvas) { 
    //TODO: Reduce the burden from multiple drawing 
    Bitmap bitmap=Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Config.ARGB_8888); 
    Canvas offscreen=new Canvas(bitmap); 
    super.onDraw(offscreen); 
    //Then draw onscreen 
    Paint p=new Paint(); 
    p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN)); 
    canvas.drawBitmap(bitmap, 0, 0, p); 
} 

ответ

7

Следующий код будет намного более эффективным.

public class MyView extends TextView{ 
    private Canvas offscreen; 

    public MyView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    public MyView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public MyView(Context context) { 
     super(context); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     //We want the superclass to draw directly to the offscreen canvas so that we don't get an infinitely deep recursive call 
     if(canvas==offscreen){ 
      super.onDraw(offscreen); 
     } 
     else{ 
      //Our offscreen image uses the dimensions of the view rather than the canvas 
      Bitmap bitmap=Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888); 
      offscreen=new Canvas(bitmap); 
      super.draw(offscreen); 
      //Create paint to draw effect 
      Paint p=new Paint(); 
      p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN)); 
      //Draw on the canvas. Fortunately, this class uses relative coordinates so that we don't have to worry about where this View is actually positioned. 
      canvas.drawBitmap(bitmap, 0, 0, p); 
     } 
    } 
} 
+0

Не создает слишком много сбора мусора, если в методе рисования создаются новые объекты? – Srin

8

Вы пробовали изменения размера растрового изображения вы создаете, будет равен только зажимных границ, а не весь размер данного холста? Я не знаю, относится ли это ко всем представлениям, но я обнаружил, что для метода onDraw для некоторых представлений задан холст размером с экран, независимо от фактического размера содержимого. Затем он зажимает холст, ограничивая его только в верхнем левом углу, рисует, а затем переводит эту часть в другое место на экране, когда он на самом деле готов отобразить весь макет. Другими словами, несмотря на то, что он имеет холст размером всего экрана, он фактически использует только небольшой кусочек. Так что вы могли бы попробовать сделать это вместо того, чтобы использовать

Bitmap bitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), ...) 

вы могли бы попробовать

Rect rect = canvas.getClipBounds(); 
int width = rect.width(); 
int height = rect.height(); 
Bitmap bitmap = Bitmap.createBitmap(width, height, ...); 

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

+0

Я думаю, что метод getClipBounds дает правильные размеры, но поскольку я не уверен, что пошел с методами 'getWidth' и' getHeight' 'View'. Это не работает, поскольку метод 'onDraw' использует какой-то смещение. Мне удалось решить это, используя хороший трюк с методом 'draw'' View', который не использует смещения. Обратите внимание, что методы рисования 'Canvas' все же используют смещения. Сначала я нашел это сбивающим с толку, но все это имеет смысл, когда вы об этом думаете. – Casebash

0

я встретил что-то подобное, где canvas.getWidth() и canvas.getHeight() возвращает ширину и высоту всего экрана, а не самого представления.

Попробуйте использовать ниже вместо этого:

Bitmap bitmap=Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888); 

Для моего случая, GetWidth() и GetHeight() возвращает мне размеры моего зрения. Удачи!

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