我的自定义视图类的onDraw()方法有问题。我的自定义视图类扩展了Constraint Layout,我想使用canvas.drawLine()方法在其上绘制一些线条,但是当应用程序启动时,屏幕上什么都没有出现。为什么?请帮助我!
我编写的所有与代码相关的自定义视图。这是我视图的最简单形式,解决了此问题后,我将使用我编写但尚未使用的一些功能来扩展类:
class WeeklyBarDiagram @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null, defStyle: Int = 0): ConstraintLayout(context, attrs, defStyle) {
private val row = listOf(
R.id.text_view_min_value,
R.id.text_view_second_min_value,
R.id.text_view_second_max_value,
R.id.text_view_max_value
)
private val column = listOf(
R.id.text_view_day1,
R.id.text_view_day2,
R.id.text_view_day3,
R.id.text_view_day4,
R.id.text_view_day5,
R.id.text_view_day6,
R.id.text_view_day7
)
private val columnDistances = listOf(0.108f, 0.222f, 0.337f, 0.452f, 0.567f, 0.681f, 0.796f)
private var maxValue: Float = 0f
private var statisticalData = listOf<Float>()
private var statisticalRatio = mutableListOf<Float>()
private var barLines = mutableListOf<Bar>()
private val paint = Paint().apply { color = Color.BLUE; strokeWidth = pxFromDP(5f) }
private var colorFirst = Color.parseColor("#353A85")
private var colorSecond = Color.parseColor("#959AC2")
private val barLineWidth: Float
private val singleBarLine: Boolean
private var isReadyToDraw = false
private val startPoint = FloatPoint() //bar starting point
private val stopPoint = FloatPoint() //bar ending point
private val firstPoint = FloatPoint() //first breaking point for two parted lines
private val secondPoint = FloatPoint() //second breaking point for two parted lines
init {
LayoutInflater.from(context).inflate(R.layout.layout_diagram, this)
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.WeeklyBarDiagram)
singleBarLine = typedArray.getBoolean(R.styleable.WeeklyBarDiagram_singleBarLine, false)
colorFirst = typedArray.getColor(R.styleable.WeeklyBarDiagram_colorFirstPart, 0)
colorSecond = typedArray.getColor(R.styleable.WeeklyBarDiagram_colorSecondPart, 0)
barLineWidth =
typedArray.getDimension(R.styleable.WeeklyBarDiagram_barLineWidth, pxFromDP(5f))
when (typedArray.getInt(R.styleable.WeeklyBarDiagram_barLineCap, 0)) {
0 -> paint.strokeCap = Paint.Cap.ROUND
1 -> paint.strokeCap = Paint.Cap.BUTT
}
paint.strokeWidth = barLineWidth
typedArray.recycle()
}
override fun onDraw(canvas: Canvas?) {
canvas?.let {
if (!isReadyToDraw) return
statisticalRatio.forEachIndexed { index, ratio ->
startPoint.x = width * columnDistances[index]
startPoint.y = height * 0.84f
//Calculations end point and some other things which can be useful for parted line
val distanceFromTopLine = height * (0.84f - 0.18f) * (1 - ratio)
val distanceFromBottomLine = height * (0.84 - 0.18f) * ratio
stopPoint.x = startPoint.x
stopPoint.y = distanceFromTopLine + height * 0.18f
if (singleBarLine) {
paint.color = colorFirst
canvas.drawLine(startPoint.x, startPoint.y, stopPoint.x, startPoint.y, paint)
}
Log.e("OnDraw", "Working")
}
}
}
//functionalities
fun setRowTexts(list: List<String>) {
row.forEachIndexed { i, v -> findViewById<TextView>(v).text = list[i] }
invalidate()
}
fun setColumnTexts(list: List<String>) {
column.forEachIndexed { i, v -> findViewById<TextView>(v).text = list[i] }
invalidate()
}
fun setMaxValue(maxValue: Float) {
this.maxValue = maxValue
//invalidate()
}
fun setStatistics(data: List<Float>) {
this.statisticalData = data
statisticalRatio.clear()
statisticalData.forEach { statisticalRatio.add(it / maxValue) }
isReadyToDraw = true
}
//utils
private fun pxFromDP(value: Float): Float {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
value,
context.resources.displayMetrics
)
}
}
我已将合并标记用于布局内容xml
以及所有其他代码在主活动中:
class TestActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
diagram.setMaxValue(700f)
diagram.setStatistics(listOf(600f, 150f, 250f, 400f, 100f, 550f, 300f))
diagram.setRowTexts(listOf("100", "300", "500", "700"))
diagram.setColumnTexts(listOf("3", "4", "5", "6", "7", "8", "9"))
}
}
isReadyToDraw在调用onDraw()时为false。在setter调用后调用diagram.invalidate()以强制更新视图。