Android 如何在画布上绘制大量性能良好的矩形?

Android 如何在画布上绘制大量性能良好的矩形?,android,performance,user-interface,canvas,2d,Android,Performance,User Interface,Canvas,2d,我必须绘制一张包含扇区、行和座位的电影院大厅地图。 目前,我有大约1000个座位(填充矩形)要画,我通过调用: canvas.drawRect(seatRect, seatPaint) 我的视图还必须支持缩放、滚动和投掷。 表演糟透了。我试图通过显式地启用硬件加速来改进它,但没有任何改变,似乎我的Nexus4(Api 22)默认启用了它 你能推荐一些高速渲染大量矩形的方法吗?因此,移动、缩放动画是平滑的 自定义视图类代码: @Override public void onDraw(Canvas

我必须绘制一张包含扇区、行和座位的电影院大厅地图。 目前,我有大约1000个座位(填充矩形)要画,我通过调用:

canvas.drawRect(seatRect, seatPaint)
我的视图还必须支持缩放、滚动和投掷。 表演糟透了。我试图通过显式地启用硬件加速来改进它,但没有任何改变,似乎我的Nexus4(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();
}
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);
    }
}
事件映射代码:

@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();
}
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中调用的任何方法都不会创建任何实例。
只有很多矩形…

现在的主要问题是,您执行了大量的绘图周期(等于您拥有的矩形数量),最好将所有这些矩形存储在object中,以减少绘图周期的数量。既然有三种状态的座位,我建议创建三条路径。我建议你这样做:

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();
}
然后,如果要将日期与此视图关联,则应执行以下操作:

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();
}
也许您还需要添加一些逻辑,以从路径中排除当前不可见的矩形,从而调整性能


我尝试在测试集的矩形上设置动画,它在200个矩形上平稳运行,我没有尝试执行严肃的基准测试,但是

你能发布你的onDraw方法的代码吗?没有看到你的代码,我只能建议你可能在onDraw中放置了太多的新对象分配,因此,我可以建议在您尝试您的方法之前在某处创建Path实例,我必须说性能有所提高,但不会太多。首先,我的hall map有大约4000个位置,将所有这些位置添加到单个路径对象中,导致应用程序挂起,然后崩溃。所以我创建了不超过200个矩形的多个路径。。。。但它仍然不能顺利呈现。我必须通过不绘制视图范围外的矩形来优化渲染,但由于它们都添加到不支持删除的路径中,我需要找到更好的方法。进一步说,我还需要渲染相应的大厅背景图像(3000x2142),这也会降低渲染性能。不确定是否有更好的方法,但我正在绘制背景,然后绘制自然大小和坐标的矩形,然后将缩放和平移应用于背景画布,我建议将其划分为块,并仅加载可能显示的块,至于路径方法,我认为在这种情况下,它必须在这种情况下进行修改-您应该只使用现在可见的矩形初始化路径(基本上每次平移或滚动视图时都需要创建新的路径),我猜绘制所有矩形和背景可能需要大量计算,我还建议只修改背景和矩形的画布,最好修改pathsI使用OpenGL解决方案,因为性能不好,而且我事件没有在每个座位上添加文本标题。一旦解决方案已准备好实施,将发布一个指向该解决方案的链接,如下所示: