我在自定义视图中有两种方法,onMeasure和onDraw。我有一个函数,用于从源设置数据并使用使视图功能无效来重绘视图。我使用onMeasure来获取计算所需的视图宽度。但是,当我使用无效函数onDraw首先被调用,然后我的onMeasure被调用。因此,我的视图宽度始终为0px。
我尝试过调用requestLayout(),然后使invalidate()重绘视图
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
val pointY = 15.px.toFloat()
var pointX = oneCellWidth.toFloat() / 2f
totalDays.forEach { day ->
val isWorkedDay = workedDays.filter { it.date == day.date }.size
if (isWorkedDay > 0) {
canvas?.drawCircle(pointX, pointY, 8f, circlePaint)
}
pointX += oneCellWidth
}
}
fun submitData(totalDays: List<Day>, workedDays: List<WorkedDateAndTime>, color: Int) {
this.totalDays = totalDays
this.workedDays = workedDays
circlePaint.color = color
oneCellWidth = viewWidth / totalDays.size
invalidate()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val widthMode = MeasureSpec.getMode(widthMeasureSpec)
val widthSize = MeasureSpec.getSize(widthMeasureSpec)
if (widthMode == MeasureSpec.EXACTLY) {
viewWidth = widthSize
}
}
需要viewWidth不具有视图宽度值。
最佳答案
我想问题正在发生,因为您在调用viewWidth
之前正在阅读View.invalidate()
。因此,当您读取viewWidth
时,它仍然具有旧值。
因此,我建议进行以下更改:
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
oneCellWidth = viewWidth / totalDays.size // Add this
val pointY = 15.px.toFloat()
var pointX = oneCellWidth.toFloat() / 2f
totalDays.forEach { day ->
val isWorkedDay = workedDays.filter { it.date == day.date }.size
if (isWorkedDay > 0) {
canvas?.drawCircle(pointX, pointY, 8f, circlePaint)
}
pointX += oneCellWidth
}
}
fun submitData(totalDays: List<Day>, workedDays: List<WorkedDateAndTime>, color: Int) {
this.totalDays = totalDays
this.workedDays = workedDays
circlePaint.color = color
// oneCellWidth = viewWidth / totalDays.size --> Remove this
requestLayout() // Add this. invalidate only request re-draw. requestLayout will request to re-measure
invalidate()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val widthMode = MeasureSpec.getMode(widthMeasureSpec)
val widthSize = MeasureSpec.getSize(widthMeasureSpec)
if (widthMode == MeasureSpec.EXACTLY) {
viewWidth = widthSize
}
}
这样,您可以避免在重新执行
viewWidth
之前读取onMeasure
的问题。进行这些更改后,您将在viewWidth
期间读取onDraw
,这总是在onMeasure
之后执行(当然,如果您调用requestLayout()
。