使用Foundatation实现的Demo是这样的。代码共50行,大家可以先跳过直接看下面的解释,跟着解释看代码。
bool tapped = false; runUiImp() { window.onBeginFrame = render; window.onMetricsChanged = window.scheduleFrame; window.onPointerDataPacket = handlePointerPacket; window.scheduleFrame(); } void render(Duration duration) { final PictureRecorder recorder = new PictureRecorder(); Size size = window.physicalSize; final Rect bounds = Rect.fromLTWH(0, 0, size.width / 2, size.height / 2); final Canvas c = Canvas(recorder, bounds); Paint background = Paint()..color = Color(0xffffffff); c.drawPaint(background); Paint centerPaint = Paint()..color = colorWith(tapped); centerPaint.style = PaintingStyle.fill; c.drawRect(centerRect(), centerPaint); Picture picture = recorder.endRecording(); SceneBuilder builder = new SceneBuilder(); builder.pushTransform(Float64List.fromList(Matrix4.identity().storage)); builder.addPicture(Offset.zero, picture); Scene scene = builder.build(); window.render(scene); } Rect centerRect() { Size size = window.physicalSize; Size centerSize = Size(100, 100) * window.devicePixelRatio; return Rect.fromLTWH( (size.width - centerSize.width) / 2, (size.height - centerSize.height) / 2, centerSize.width, centerSize.height); } bool inRect(double x, double y) { Rect rect = centerRect(); return x < rect.right && x > rect.left && y < rect.bottom && y > rect.top; } void handlePointerPacket(PointerDataPacket dataPacket) { PointerData data = dataPacket.data.first; if (inRect(data.physicalX, data.physicalY)) { tapped = !tapped; window.scheduleFrame(); } }
整个实现的核心是两个方法render
和handlePointerPacket
.
render
方法给出绘制内容的逻辑,其中调用Canvas的一系列draw方法,分别绘制了背景和方块。
布局需要手动维护,在Demo的实现中,centerRect
方法提供了居中布局的实现。
handlePointerPacket
实现了点击事件的处理,实现进行hit test, 然后修改tapped属性,并调用window.scheduleFrame
触发页面的刷新。
从这个Demo中可以看出: Foundation提供了Flutter应用需要的最基础功能,但是实现的逻辑相对复杂。
开发者需要手动计算所有的布局,实现绘制逻辑,对于事件处理,需要实现完整的hit test。
在这样简单的Demo中是可行的,但是Foundation提供的接口来实现一个正常规模的APP,对开发者来说简直是噩梦。