2015-07-23 3 views
4

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

canvas.drawRect(seatRect, seatPaint) 

мой взгляд, должен также поддерживать масштабирование, прокрутка и брыкаться. Спектакль ужасен. Я попытался улучшить его, явно включив аппаратное ускорение, но ничего не изменилось. По-моему, он был включен по умолчанию на моем Nexus 4 (Api 22)

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

Пользовательский код Просмотр класс:

@Override 
public void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 

    canvas.save(); 
    canvas.scale(mScaleFactor, mScaleFactor); // scaling support 
    canvas.translate(mTranslateX, mTranslateY); // scrolling support 

    if (mEventMap != null) { 
     mEventMap.paint(canvas); 
    } 

    canvas.restore(); 
} 

код EventMap:

public void paint(Canvas canvas) { 
    for (EventPlace place : places) { 
     if (place.isSelected()) 
      placePaint.setColor(0xFF00FF00); 
     else if (place.isAvailable()) 
      placePaint.setColor(place.getColor()); 
     else 
      placePaint.setColor(0xFF000000); 

     canvas.drawRect(place.getBounds(), placePaint); 
    } 
} 

Ни один из методов, называемых в OnDraw не создает каких-либо экземпляров. Есть только много прямоугольников ...

+0

Можете ли вы опубликовать код вашего OnDraw метода? – Chaosit

+0

Не видя своего кода, я могу только предположить, что вы можете добавить слишком много новых объектов в onDraw, и поэтому я могу предложить создать экземпляр Path где-то перед отправкой ничьей – Chaosit

ответ

2

Основная проблема, с которой вы сейчас сталкиваетесь, в основном состоит в том, что вы выполняете большое количество циклов рисования (равное количеству найденных вами Ректов), лучше хранить все эти прямоугольники в объекте Path, чтобы уменьшить количество циклов рисования. Поскольку у вас есть три состояния мест, я предлагаю создать три Пути. Я предложил бы делать что-то вроде этого:

private void init() { 
    mSelectedPath = new Path(); 
    mAvailablePath = new Path(); 
    mUnavalablePath = new Path(); 

    mAvailablePaint = new Paint(); 
    mSelectedPaint = new Paint(); 
    mUnavalablePaint = new Paint(); 

    mUnavalablePaint.setColor(Color.RED); 
    mSelectedPaint.setColor(Color.YELLOW); 
    mAvailablePaint.setColor(Color.GREEN); 

    for (EventPlace place : mData) { 
     if (place.isSelected()) 
      mSelectedPath.addRect(rectF, Path.Direction.CW); 
     else if (place.isAvailable()) 
      mAvailablePath.addRect(rectF, Path.Direction.CW); 
     else 
      mUnavalablePath.addRect(rectF, Path.Direction.CW); 
    } 
} 

Тогда, когда вы хотите связать дату с этим видом вы должны сделать что-то вроде этого:

public void setData(List<EventPlace> data) { 
    mData = data; 
    init(); 
    invalidate(); 
} 

На самом деле вы можете сделать это, как вам нравится, просто держать в виду, что вам нужно вызвать метод init, а затем сделать недействительным. И в OnDraw:

@Override 
protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 

    canvas.save(); 
    canvas.scale(mScaleFactor, mScaleFactor); // scaling support 
    canvas.translate(mTranslateX, mTranslateY); // scrolling support 

    canvas.drawPath(mAvailablePath, mAvailablePaint); 
    canvas.drawPath(mUnavalablePath, mUnavalablePaint); 
    canvas.drawPath(mSelectedPath, mSelectedPaint); 

    canvas.restore(); 
} 

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

Я попробовал анимировать свой подход на тестовом наборе прямоугольников и он работает гладко с 200 прямоугольниками, я не пытался выполнять серьезный тест, хотя

+0

Я пробовал ваш подход и должен сказать, что производительность улучшилась, но не очень много. Прежде всего, моя карта зала насчитывает ~ 4000 мест, добавляя все это в один объект Path, вызвавший винт приложения, сопровождаемый сбоем. Поэтому я создал несколько путей (путей), вмещающих не более 200 прямоугольников. – ievgen

+0

... но все же он не отображается гладко. Мне нужно оптимизировать рендеринг, не вычеркивая прямоугольники диапазона обзора, но поскольку все они добавлены в Путь, который не поддерживает удаление, мне нужно найти лучший подход. Идти дальше У меня также есть соответствующее огромное фоновое изображение зала (3000x2142), которое мне нужно сделать, это также замедляет производительность рендеринга. Не уверен, что есть лучший подход, но я рисую фон, а затем прямоугольники в натуральном размере и координатах, а затем применяю масштабирование и перевод на холст. – ievgen

+0

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

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