[Flutter笔记]RenderProxyBox

2,031 阅读1分钟
官方文档:api.flutter.dev/flutter/ren…

Dartpad示例:dartpad.dev/05d77d19ae7…

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Shimmer(
            gradient: gradient,
            child: Container(
              width: 500,
              height: 500,
              color: Colors.red,
            ),
          ),
        ),
      ),
    );
  }
}

final gradient = LinearGradient(
  begin: Alignment.topLeft,
  end: Alignment.centerRight,
  colors: <Color>[
    Colors.grey[300],
    Colors.grey[300],
    Colors.grey[100],
    Colors.grey[300],
    Colors.grey[300]
  ],
  stops: const <double>[0.0, 0.35, 0.5, 0.65, 1.0],
);

class Shimmer extends SingleChildRenderObjectWidget {
  final Gradient gradient;

  const Shimmer({
    Key key,
    @required this.gradient,
    Widget child,
  }) : super(key: key, child: child);

  @override
  RenderObject createRenderObject(BuildContext context) {
    return RenderShimmer(this.gradient);
  }
}

class RenderShimmer extends RenderProxyBox {
  final Gradient gradient;

  RenderShimmer(this.gradient);

  @override
  bool get alwaysNeedsCompositing => child != null;

  @override
  void paint(PaintingContext context, Offset offset) {
    if (child != null) {
      assert(needsCompositing);

      var rect = offset & child.size;
      context.canvas.saveLayer(rect, Paint());

      context.paintChild(child, offset);
      final gradientPaint = Paint()
        ..blendMode = BlendMode.srcIn
        ..shader = gradient.createShader(rect);
      print('paint');
      context.canvas.drawRect(rect, gradientPaint);

      context.canvas.restore();
    }
  }
}

参考:

juejin.cn/post/684490…