自定义视图不呈现

Custom View not rendering

这是我第一次尝试在 Android 中创建自定义视图。但是,我似乎遗漏了一些东西并且不知道如何调试这个问题。我编写了一个自定义视图,用于在 Android 中绘制条形图,其值位于条形图下方。我在代码中的onDraw方法如下:

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    if (mBars == null) {
        return
    }
    canvas.save()
    val rectBaseLine = measuredHeight * FRACTIONAL_MAX_BAR_HEIGHT + convertDpToPixel(TOP_MARGIN_FOR_BAR, context);
    canvas.translate(0f, rectBaseLine.toFloat())

    mBars.forEach {
        canvas.drawRoundRect(it.mRect,
                BAR_CORNER_RADIUS, BAR_CORNER_RADIUS,
                mapToPaints.getValue(it.paintType))

        var textWidth = textPaint.measureText(it.num.toString())

        canvas.drawText(it.num.toString(),
                it.mRect.left + (it.mRect.right - it.mRect.left) / 2 - textWidth / 2,
                convertSpToPixel(TEXT_SIZE, context) + convertDpToPixel(DISTANCE_BW_TEXT_N_BAR, context),
                mapToTextPaints.getValue(it.paintType))
    }

    canvas.restore()
}

fun prepareBarsArr(arr: IntArray) {
    val max = arr.max();
    val viewHeight = measuredHeight
    val rectHeight = measuredHeight * FRACTIONAL_MAX_BAR_HEIGHT /*- ( convertSpToPixel(TEXT_SIZE, context) +  convertDpToPixel(DISTANCE_BW_TEXT_N_BAR, context))*/;
    val width = measuredWidth
    widthPerBar = (width - INTER_BAR_GAP * (arr.size - 1)) / arr.size

    var currentX = -widthPerBar - INTER_BAR_GAP
    mBars = Array<BarDetails>(arr.size, {
        val desiredHeight = arr[it] * rectHeight / max!!
        currentX += widthPerBar + INTER_BAR_GAP
        val mRect = RectF(currentX.toFloat(), 0f, (currentX + widthPerBar).toFloat(), (-desiredHeight).toFloat());
        BarDetails(mRect, arr[it], STATEPAINTS.NORMAL)
    });


    invalidate()
}

mBars 存储 Bar 相关信息,例如:Rect 对象、数值(有助于确定 bar 的高度)、要使用的绘画等。

问题是此代码在模拟器上运行完美,但在我的设备(使用 Lenovo Zuk Z2 Plus)上,它不绘制条形图。我检查了一些帖子并尝试了 hardwareAccelerated ="true/false" 的不同组合 和 drawRoundRect/drawRect 等。当 hardwareAccelerated 为 false 并且我正在使用 drawRect 时,只有 1 种组合会在我的设备上显示条形图。但是,当我使用 RoundedRect 时,条形图不会显示。不知道这是否是设备特定问题,因为我只有 1 台设备可以测试。无论哪种方式,有关如何调试的一些要点都会有所帮助。

通过重写创建柱的逻辑解决了这个问题。在有问题的代码中,我曾经翻译 canvas 然后从底部到顶部绘制 bars/Rect 。我只是更改了计算以创建 Rect,顶部位于 Rect 的顶部,底部位于 rectHeight。以下是修改后的代码,它甚至渲染了 RoundedRect。我的清单文件中有 android:hardwareAccelerated="false"。另外,早些时候我正在做保存和恢复,现在不需要了,因为 canvas 的翻译还没有完成。

fun prepareBarsArr(arr: IntArray) {
    val max = arr.max();
    val viewHeight = measuredHeight
    val rectHeight = measuredHeight * FRACTIONAL_MAX_BAR_HEIGHT /*- ( convertSpToPixel(TEXT_SIZE, context) +  convertDpToPixel(DISTANCE_BW_TEXT_N_BAR, context))*/;
    val width = measuredWidth
    widthPerBar = (width - INTER_BAR_GAP * (arr.size + 1)) / arr.size

    var currentX = INTER_BAR_GAP
    mBars = Array<BarDetails>(arr.size, {
        val desiredHeight = arr[it] * rectHeight / max!!
        val mRect = RectF(currentX.toFloat(),
                rectHeight - desiredHeight,
                (currentX + widthPerBar).toFloat(),
                (rectHeight).toFloat()
        );
        currentX += widthPerBar + INTER_BAR_GAP
        BarDetails(mRect, arr[it], STATEPAINTS.NORMAL)
    });


    invalidate()
}

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    if (mBars == null) {
        return
    }

    /*val rectBaseLine = measuredHeight * FRACTIONAL_MAX_BAR_HEIGHT + convertDpToPixel(TOP_MARGIN_FOR_BAR, context);*/ /*- ( convertSpToPixel(TEXT_SIZE, context) +  convertDpToPixel(DISTANCE_BW_TEXT_N_BAR, context))*/;
    /*canvas.translate(0f, rectBaseLine.toFloat())*/

    mBars.forEach {
        canvas.drawRoundRect(it.mRect,
                BAR_CORNER_RADIUS, BAR_CORNER_RADIUS,
                mapToPaints.getValue(it.paintType))

        var textWidth = textPaint.measureText(it.num.toString())

        canvas.drawText(it.num.toString(),
                it.mRect.left + (it.mRect.right - it.mRect.left) / 2 - textWidth / 2,
                convertSpToPixel(TEXT_SIZE, context) + convertDpToPixel(DISTANCE_BW_TEXT_N_BAR, context) + it.mRect.bottom,
                mapToTextPaints.getValue(it.paintType))
    }
}

如果有人想补充,我很感激这背后的推理。我在 canvas 翻译或保存和恢复方面做错了吗?我不知道,为什么它在模拟器上运行良好而不是在设备上运行。