如何在Kotlin中绘制矩形?解决跨Activity传数组至自定义View的问题
解决自定义View无法接收Activity传递数组的问题
看起来你遇到的核心问题是自定义View类没有接收外部数据的入口——你在Activity里拿到了从其他页面传来的各种ArrayList,但你的Canvass类并没有提供构造方法来接收这些数据,所以在onDraw方法里自然没法访问到这些数组。我来帮你一步步修正:
第一步:给自定义View添加带参数的构造方法
修改你的Canvass类,把需要用到的数组作为构造参数传入,并保存为类的属性:
class Canvass( context: Context, val layerHeight: ArrayList<Double>, val soilSpecificWeight: ArrayList<Double>, val cohesion: ArrayList<Double>, val frictionAngle: ArrayList<Double>, val mpEffectiveStress: ArrayList<Double>, val voidRatio: ArrayList<Double>, val compressionIndex: ArrayList<Double>, val recompressionIndex: ArrayList<Double>, val bearingCapacityIndex: ArrayList<Double> ) : View(context) { override fun onDraw(canvas: Canvas) { super.onDraw(canvas) // 别忘了调用父类的onDraw方法 canvas.drawRGB(255, 255, 255) val width = width.toFloat() // 直接转成Float减少后续类型转换 // 用apply方法简化Paint初始化,代码更简洁 val footingPaint = Paint().apply { setARGB(255, 128, 128, 128) } val textPaint = Paint().apply { setARGB(255, 255, 255, 255) } val brush3 = Paint().apply { setARGB(255, 138, 36, 36) } val brush4 = Paint().apply { setARGB(255, 138, 36, 36) } // 绘制基础矩形 canvas.drawRect(width/2 -10, 0f, width/2 +10, 40f, footingPaint) canvas.drawRect(70f, 40f, width -70, 80f, footingPaint) // 修正循环:0..layerHeight.size会导致索引越界,改用until避免 for(i in 0 until layerHeight.size){ // 这里就可以用layerHeight[i]等数据绘制对应图层了 // 示例:根据每层高度绘制不同的矩形 val layerTop = 80f + (0 until i).sumOf { layerHeight[it].toFloat() } val layerBottom = layerTop + layerHeight[i].toFloat() canvas.drawRect(70f, layerTop, width -70, layerBottom, brush3) } } }
第二步:在Activity中传递数据给自定义View
修改你的drawrect方法,创建Canvass实例时把从Intent获取的所有数组传进去:
fun drawrect(view: View){ val layout1 = findViewById<ConstraintLayout>(R.id.layout1) // 安全转换Intent数据,避免类型转换异常导致崩溃 val layerHeight = intent.getSerializableExtra("layerheight") as? ArrayList<Double> ?: arrayListOf() val soilSpecificWeight = intent.getSerializableExtra("soilspecificweight") as? ArrayList<Double> ?: arrayListOf() val cohesion = intent.getSerializableExtra("cohesion") as? ArrayList<Double> ?: arrayListOf() val frictionAngle = intent.getSerializableExtra("frictionangle") as? ArrayList<Double> ?: arrayListOf() val mpEffectiveStress = intent.getSerializableExtra("mpeffectivestress") as? ArrayList<Double> ?: arrayListOf() val voidRatio = intent.getSerializableExtra("voidratio") as? ArrayList<Double> ?: arrayListOf() val compressionIndex = intent.getSerializableExtra("compressionindex") as? ArrayList<Double> ?: arrayListOf() val recompressionIndex = intent.getSerializableExtra("recompressionindex") as? ArrayList<Double> ?: arrayListOf() val bearingCapacityIndex = intent.getSerializableExtra("bearingcapacityindex") as? ArrayList<Double> ?: arrayListOf() // 传递所有数据给Canvass实例 val background = Canvass( this, layerHeight, soilSpecificWeight, cohesion, frictionAngle, mpEffectiveStress, voidRatio, compressionIndex, recompressionIndex, bearingCapacityIndex ) layout1.addView(background) }
额外提示
- 空指针防护:用
as?和?:操作符安全转换数据,即使Intent中没有对应key,也会返回空ArrayList避免崩溃。 - 循环越界问题:原代码的
0..layerheight.size会访问到超出数组长度的索引,0 until layerheight.size是更安全的写法。 - 图层绘制逻辑:示例中用累加高度的方式绘制分层矩形,你可以根据自己的需求调整绘制规则。
内容的提问来源于stack exchange,提问作者B. Ozturk




