如何在画布上画出很多具有良好性能的矩形?

iev*_*gen 6 performance user-interface android 2d canvas

我必须使用扇区,行和座位来渲染电影院大厅地图.目前我有大约1000个座位(填充矩形)可供绘制,我通过调用以下方式为每个座位执行此操作:

canvas.drawRect(seatRect, seatPaint)
Run Code Online (Sandbox Code Playgroud)

我的观点也必须支持缩放,滚动和投掷.表现很糟糕.我尝试通过明确启用硬件加速来改进它,但没有任何改变,它似乎在我的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();
}
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

onDraw中调用的所有方法都不会创建任何实例.只有很多矩形......

Cha*_*sit 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,当您想将日期与此视图关联时,您应该执行以下操作:

public void setData(List<EventPlace> data) {
    mData = data;
    init();
    invalidate();
}
Run Code Online (Sandbox Code Playgroud)

实际上你可以随心所欲地做,只要记住你必须调用 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();
}
Run Code Online (Sandbox Code Playgroud)

也许您还想添加一些逻辑来从路径中排除那些目前不可见的矩形,以调整性能。

我尝试在矩形测试集上对我的方法进行动画处理,它在 200 个矩形上运行顺利,但我没有尝试执行严格的基准测试