自定义视图不呈现
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 翻译或保存和恢复方面做错了吗?我不知道,为什么它在模拟器上运行良好而不是在设备上运行。
这是我第一次尝试在 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 翻译或保存和恢复方面做错了吗?我不知道,为什么它在模拟器上运行良好而不是在设备上运行。