欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用Android封裝一個有趣的Loading組件

 更新時間:2022年08月08日 10:34:02   作者:島上碼農  
這篇文章我們將利用Android封裝一個可以自定義配置前景色和背景色的Loading組件,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下

前言

在上一篇普通的加載千篇一律,有趣的 loading 萬里挑一 中,我們介紹了使用Path類的PathMetrics屬性來控制繪制點在路徑上運動來實現(xiàn)比較有趣的loading效果。有評論說因為是黑色背景,所以看著好看。黑色背景確實顯得高端一點,但是并不是其他配色也不行,本篇我們來封裝一個可以自定義配置前景色和背景色的Loading組件。

組件定義

loading組件共定義4個入口參數(shù):

  • 前景色:繪制圖形的前景色;
  • 背景色:繪制圖形的背景色;
  • 圖形尺寸:繪制圖形的尺寸;
  • 加載文字:可選,如果有文字就顯示,沒有就不顯示。

得到的Loading組件類如下所示:

class LoadingAnimations extends StatefulWidget {
  final Color bgColor;
  final Color foregroundColor;
  String? loadingText;
  final double size;
  LoadingAnimations(
      {required this.foregroundColor,
      required this.bgColor,
      this.loadingText,
      this.size = 100.0,
      Key? key})
      : super(key: key);

  @override
  _LoadingAnimationsState createState() => _LoadingAnimationsState();
}

圓形Loading

我們先來實現(xiàn)一個圓形的loading,效果如下所示。

這里繪制了兩組沿著一個大圓運動的軸對稱的實心圓,半徑依次減小,圓心間距隨著動畫時間逐步拉大。實際上實現(xiàn)的核心還是基于PathPathMetrics。具體實現(xiàn)代碼如下:

_drawCircleLoadingAnimaion(
      Canvas canvas, Size size, Offset center, Paint paint) {
  final radius = boxSize / 2;
  final ballCount = 6;
  final ballRadius = boxSize / 15;

  var circlePath = Path()
    ..addOval(Rect.fromCircle(center: center, radius: radius));

  var circleMetrics = circlePath.computeMetrics();
  for (var pathMetric in circleMetrics) {
    for (var i = 0; i < ballCount; ++i) {
      var lengthRatio = animationValue * (1 - i / ballCount);
      var tangent =
          pathMetric.getTangentForOffset(pathMetric.length * lengthRatio);

      var ballPosition = tangent!.position;
      canvas.drawCircle(ballPosition, ballRadius / (1 + i), paint);
      canvas.drawCircle(
          Offset(size.width - tangent.position.dx,
              size.height - tangent.position.dy),
          ballRadius / (1 + i),
          paint);
    }
  }
}

其中路徑比例為lengthRatio,通過animationValue乘以一個系數(shù)使得實心圓的間距越來越大 ,同時通過Offset(size.width - tangent.position.dx, size.height - tangent.position.dy)繪制了一組對對稱的實心圓,這樣整體就有一個圓形的效果了,動起來也會更有趣一點。

橢圓運動Loading

橢圓和圓形沒什么區(qū)別,這里我們搞個漸變的效果看看,利用之前介紹過的Paintshader可以實現(xiàn)漸變色繪制效果。

實現(xiàn)代碼如下所示。

final ballCount = 6;
final ballRadius = boxSize / 15;

var ovalPath = Path()
  ..addOval(Rect.fromCenter(
      center: center, width: boxSize, height: boxSize / 1.5));
paint.shader = LinearGradient(
  begin: Alignment.topLeft,
  end: Alignment.bottomRight,
  colors: [this.foregroundColor, this.bgColor],
).createShader(Offset.zero & size);
var ovalMetrics = ovalPath.computeMetrics();
for (var pathMetric in ovalMetrics) {
  for (var i = 0; i < ballCount; ++i) {
    var lengthRatio = animationValue * (1 - i / ballCount);
    var tangent =
        pathMetric.getTangentForOffset(pathMetric.length * lengthRatio);

    var ballPosition = tangent!.position;
    canvas.drawCircle(ballPosition, ballRadius / (1 + i), paint);
    canvas.drawCircle(
        Offset(size.width - tangent.position.dx,
            size.height - tangent.position.dy),
        ballRadius / (1 + i),
        paint);
  }
}

當然,如果漸變色的顏色更豐富一點會更有趣些。

貝塞爾曲線Loading

通過貝塞爾曲線構建一條Path,讓一組圓形沿著貝塞爾曲線運動的Loading效果也很有趣。

原理和圓形的一樣,首先是構建貝塞爾曲線Path,代碼如下。

var bezierPath = Path()
  ..moveTo(size.width / 2 - boxSize / 2, center.dy)
  ..quadraticBezierTo(size.width / 2 - boxSize / 4, center.dy - boxSize / 4,
      size.width / 2, center.dy)
  ..quadraticBezierTo(size.width / 2 + boxSize / 4, center.dy + boxSize / 4,
      size.width / 2 + boxSize / 2, center.dy)
  ..quadraticBezierTo(size.width / 2 + boxSize / 4, center.dy - boxSize / 4,
      size.width / 2, center.dy)
  ..quadraticBezierTo(size.width / 2 - boxSize / 4, center.dy + boxSize / 4,
      size.width / 2 - boxSize / 2, center.dy);

這里實際是構建了兩條貝塞爾曲線,先從左邊到右邊,然后再折回來。之后就是運動的實心圓了,這個只是數(shù)量上多了,ballCount30,這樣效果看著就有一種拖影的效果。

var ovalMetrics = bezierPath.computeMetrics();
for (var pathMetric in ovalMetrics) {
  for (var i = 0; i < ballCount; ++i) {
    var lengthRatio = animationValue * (1 - i / ballCount);
    var tangent =
        pathMetric.getTangentForOffset(pathMetric.length * lengthRatio);

    var ballPosition = tangent!.position;
    canvas.drawCircle(ballPosition, ballRadius / (1 + i), paint);
    canvas.drawCircle(
        Offset(size.width - tangent.position.dx,
            size.height - tangent.position.dy),
        ballRadius / (1 + i),
        paint);
  }
}

這里還可以改變運動方向,實現(xiàn)一些其他的效果,例如下面的效果,第二組圓球的繪制位置實際上是第一組圓球的x、y坐標的互換。

var lengthRatio = animationValue * (1 - i / ballCount);
var tangent =
    pathMetric.getTangentForOffset(pathMetric.length * lengthRatio);

var ballPosition = tangent!.position;
canvas.drawCircle(ballPosition, ballRadius / (1 + i), paint);
canvas.drawCircle(Offset(tangent.position.dy, tangent.position.dx),
    ballRadius / (1 + i), paint);

組件使用

我們來看如何使用我們定義的這個組件,使用代碼如下,我們用Future延遲模擬了一個加載效果,在加載過程中使用loading指示加載過程,加載完成后顯示圖片。

class _LoadingDemoState extends State<LoadingDemo> {
  var loaded = false;

  @override
  void initState() {
    super.initState();
    Future.delayed(Duration(seconds: 5), () {
      setState(() {
        loaded = true;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: Text('Loading 使用'),
      ),
      body: Center(
        child: loaded
            ? Image.asset(
                'images/beauty.jpeg',
                width: 100.0,
              )
            : LoadingAnimations(
                foregroundColor: Colors.blue,
                bgColor: Colors.white,
                size: 100.0,
              ),
      ),
    );
  }

最終運行的效果如下,源碼已提交至:繪圖相關源碼,文件名為loading_animations.dart

總結

本篇介紹了Loading組件的封裝方法,核心要點還是利用Path和動畫控制繪制元素的運動軌跡來實現(xiàn)更有趣的效果。在實際應用過程中,也可以根據(jù)交互設計的需要,做一些其他有趣的加載動效,提高等待過程的趣味性。

到此這篇關于利用Android封裝一個有趣的Loading組件的文章就介紹到這了,更多相關Android封裝Loading組件內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論