Flutter - 动画使用及自定义动画组件(tabbar跳动动画或文字抖动)

news2025/3/1 1:16:10

demo 地址: https://github.com/iotjin/jh_flutter_demo
代码不定时更新,请前往github查看最新代码

Flutter - 动画组件(tabbar跳动动画或文字抖动)

  • 效果图
  • 动画简介
    • 动画类型
    • Flutter动画的一些概念
  • 常用动画实现
    • 隐式动画
    • Tween动画
    • Curve动画
    • Hero动画
    • 组合动画
  • 自定义动画组件:
    • 跳动动画,默认先放大再缩小再还原
    • 缩放动画,默认放大再还原
    • 缩放动画2,默认缩小再还原
    • 抖动(位移)动画,支持上下/左右抖动,默认左右抖动

APP 主页面的tabbar点击时有些有一些tabbar图标缩放或跳动动画,还有文字点击时有抖动效果
本文通过flutter 实现一些缩放或位移动画。封装成几个自定义组件。
这几个自定义的动画组件可以实现子组件通过属性或者方法调用动画
动画效果:抖动,左右晃动,先放大再缩小等,也支持自定义

类似效果的三方库:
animate_do: ^3.0.2

文章:
flutter动画简介

效果图

请添加图片描述

请添加图片描述

动画简介

动画是指将一系列静态图像连续播放,形成一种视觉上的动态效果。在Flutter中,动画是通过对属性进行插值计算,逐步改变属性值,从而实现动态效果的。

在Flutter中,动画是通过一系列的动画对象和控制器来实现的。动画对象通常是一个值的插值器,可以将一个值从一个范围映射到另一个范围。Flutter中提供了多种类型的动画对象,如Tween、Curve等。
动画控制器则用于控制动画的状态和进度。控制器可以启动、停止、反转动画,并且可以监听动画的状态变化和进度变化。Flutter中提供了AnimationController类来实现动画控制器。

动画类型

在Flutter中,动画可以分为两种类型:显式动画和隐式动画。

  • 显式动画:这种动画是由开发人员自己定义的,通常使用Flutter提供的AnimationController动画类来实现。开发人员可以通过设置控制器的属性来控制动画的开始、结束、暂停和恢复等操作。例如,Animation、Tween和Curve等类可以用于创建各种类型的动画效果。

  • 隐式动画:这种动画是由框架自动处理的,通过AnimatedWidget类来实现的,它会自动根据动画的变化来更新UI界面。例如,当应用中的Widget发生变化时,Flutter会自动创建一个动画来平滑地过渡到新的Widget状态。

Flutter动画的一些概念

  • Flutter动画框架是基于Animation类的。
  • Animation类是一个抽象类,它定义了动画的基本属性和方法。
  • Flutter提供了许多Animation的子类,包括TweenCurveIntervalAnimationController等。
  • Tween类用于定义动画的起始值和结束值,Curve类用于定义动画的加速和减速曲线,Interval类用于定义动画的时间间隔,AnimationController类用于定义动画的控制器。
  • AnimationController:动画控制器,用于控制动画的开始、结束、暂停、恢复等操作。可以设置动画的持续时间、速度曲线等属性。
  • Tween:插值器,用于计算属性值的变化。可以设置属性的起始值和结束值,以及插值的类型(如线性插值、曲线插值等)。它可以是一个数字、一个颜色、一个矩形或任何其他类型的值。
  • Animation:动画对象,用于保存属性值的变化。表示动画的开始和结束值。它可以是一个数字、一个颜色、一个矩形或任何其他类型的值。可以通过addListener()方法监听动画的变化,并在回调函数中更新UI。
  • Listener:监听动画的状态变化,例如动画开始、结束、停止等。
  • AnimatedBuilder:动画构建器,用于构建动画组件。可以将Animation对象传递给子组件,使子组件随着动画变化而变化。
  • Curve:表示动画的时间曲线,用于控制动画的变化速度。可以设置曲线类型(如匀速、加速、减速、先加速后减速等)。
  • Hero动画:用于在路由跳转时实现两个页面中同一元素的平滑过渡效果。可以将两个页面中的同一元素包裹在Hero组件中,并设置唯一的tag值。
  • AnimatedSwitcher:用于在多个组件之间实现平滑的切换效果。可以将多个组件包裹在AnimatedSwitcher组件中,并在组件切换时设置不同的key值。

Flutter的 AnimationStatus 枚举类型定义了动画的四种状态(begin: 0.0, end: 1.0时):

    1. dismissed:动画已经停止,并且值已经回到初始状态。即动画的值为0.0。
    1. forward:动画正在正向播放。即动画的值从0.0逐渐增加到1.0。(正向运行)
    1. reverse:动画正在反向播放。即动画的值从1.0逐渐减少到0.0。(反向运行)
    1. completed:动画已经停止,并且值已经达到最终状态。即动画的值为1.0。

动画的控制方法:

  • forward:正向执行动画。
  • reverse:反向执行动画。
  • repeat:反复执行动画。
  • reset:重置动画。

Flutter中常见的 Curve 类型有以下几种:

一个Curve 类型动画的网站
https://cubic-bezier.com/

Curves.linear:线性动画曲线,即匀速运动,适用于需要匀速移动的场景。
Curves.ease:默认的缓动动画曲线,适用于大部分场景。
Curves.easeIn:快速进入动画曲线,适用于需要快速进入的场景,如按钮点击等。
Curves.easeOut:快速退出动画曲线,适用于需要快速退出的场景,如弹窗关闭等。
Curves.easeInOut:快速进入并快速退出动画曲线,适用于需要快速进入并快速退出的场景,如页面切换等。
Curves.fastLinearToSlowEaseIn:快速匀速运动然后慢速进入动画曲线,适用于需要快速匀速运动然后慢速进入的场景,如列表滚动等。
Curves.bounceIn:弹性进入动画曲线,适用于需要弹性进入的场景,如弹窗出现等。
Curves.bounceOut:弹性退出动画曲线,适用于需要弹性退出的场景,如弹窗关闭等。
Curves.elasticIn:弹性进入动画曲线,适用于需要弹性进入的场景,如下拉刷新等。
Curves.elasticOut:弹性退出动画曲线,适用于需要弹性退出的场景,如列表滑动到底部等。
不同的 Curve 类型适用于不同的场景,根据具体的需求来选择合适的 Curve 类型可以让动画效果更加自然和流畅。
例如,如果需要实现一个快速进入的按钮点击效果,可以选择 Curves.easeIn;
如果需要实现一个缓慢的列表滚动效果,可以选择 Curves.fastLinearToSlowEaseIn;
如果需要实现一个弹性出现的弹窗效果,可以选择 Curves.bounceIn 等。

常用动画实现

Flutter提供了多种实现动画的方式,包括一些隐式动画(如Opacity、AnimatedContainer、AnimatedPositioned),Tween动画、Curve动画、组合动画等。

隐式动画

可以使用 Flutter 的隐式动画来实现平滑的过渡效果。以下是一些常见的隐式动画示例:

  1. Opacity 动画:通过改变透明度来实现淡入淡出效果。
Opacity(
  opacity: _visible ? 1.0 : 0.0,
  duration: Duration(milliseconds: 500),
  child: Container(
    // your widget
  ),
)
  1. 缩放动画:通过改变尺寸来实现缩放效果。
AnimatedContainer(
  duration: Duration(milliseconds: 500),
  curve: Curves.easeInOut,
  width: _expanded ? 200.0 : 100.0,
  height: _expanded ? 200.0 : 100.0,
  child: Container(
    // your widget
  ),
)
  1. 旋转动画:通过改变角度来实现旋转效果。
AnimatedContainer(
  duration: Duration(milliseconds: 500),
  curve: Curves.easeInOut,
  transform: Matrix4.rotationZ(_expanded ? pi / 4 : 0),
  child: Container(
    // your widget
  ),
)
  1. 平移动画:通过改变位置来实现平移效果。
AnimatedPositioned(
  duration: Duration(milliseconds: 500),
  curve: Curves.easeInOut,
  left: _expanded ? 100.0 : 0.0,
  top: _expanded ? 100.0 : 0.0,
  child: Container(
    // your widget
  ),
)
  1. 颜色动画:通过改变颜色来实现颜色过渡效果。
AnimatedContainer(
  duration: Duration(milliseconds: 500),
  curve: Curves.easeInOut,
  color: _expanded ? Colors.red : Colors.blue,
  child: Container(
    // your widget
  ),
)

Tween动画

Tween动画是Flutter中最基本的动画类型之一。它用于在两个值之间进行插值,从而创建一个平滑的过渡效果。例如,我们可以使用Tween动画在两个颜色之间创建一个渐变效果。以下示例代码演示了如何使用Tween动画创建一个颜色渐变效果:

class ColorTweenAnimation extends StatefulWidget {
  
  _ColorTweenAnimationState createState() => _ColorTweenAnimationState();
}

class _ColorTweenAnimationState extends State<ColorTweenAnimation>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<Color> _animation;

  
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    )..repeat(reverse: true);
    _animation = ColorTween(
      begin: Colors.red,
      end: Colors.blue,
    ).animate(_controller);
  }

  
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return Container(
      color: _animation.value,
      height: 200,
      width: 200,
    );
  }
}

Curve动画

Curve动画用于控制动画的时间曲线。Flutter提供了许多预定义的Curve曲线,例如线性曲线、加速曲线、减速曲线等。以下示例代码演示了如何使用Curve动画创建一个弹跳效果:

class BounceAnimation extends StatefulWidget {
  
  _BounceAnimationState createState() => _BounceAnimationState();
}

class _BounceAnimationState extends State<BounceAnimation>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<double> _animation;

  
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(milliseconds: 1500),
      vsync: this,
    )..repeat(reverse: true);
    _animation = Tween<double>(
      begin: 0,
      end: 100,
    ).animate(
      CurvedAnimation(
        parent: _controller,
        curve: Curves.bounceOut,
      ),
    );
  }

  
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.bottomCenter,
      child: AnimatedBuilder(
        animation: _animation,
        builder: (context, child) {
          return Container(
            height: _animation.value,
            width: 50,
            color: Colors.red,
          );
        },
      ),
    );
  }
}

Hero动画

Hero动画是Flutter中非常流行的一种动画类型。它用于在不同屏幕之间平滑地过渡共享元素。例如,我们可以在两个不同的屏幕之间创建一个Hero动画,使得共享元素平滑地过渡到新的屏幕状态。以下示例代码演示了如何使用Hero动画创建一个共享元素过渡效果:

class HeroAnimation extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      body: GestureDetector(
        onTap: () {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (_) => HeroDetailScreen()),
          );
        },
        child: Hero(
          tag: 'image',
          child: Image.network(
            'https://picsum.photos/250?image=9',
            height: 300,
            width: double.infinity,
            fit: BoxFit.cover,
          ),
        ),
      ),
    );
  }
}

class HeroDetailScreen extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      body: GestureDetector(
        onTap: () {
          Navigator.pop(context);
        },
        child: Hero(
          tag: 'image',
          child: Image.network(
            'https://picsum.photos/250?image=9',
            height: double.infinity,
            width: double.infinity,
            fit: BoxFit.cover,
          ),
        ),
      ),
    );
  }
}

组合动画

组合动画可以将多个动画组合在一起,使动画效果更加丰富。

AnimationController _controller;
Animation<double> _animation1;
Animation<double> _animation2;


void initState() {
  super.initState();
  _controller = AnimationController(
    duration: const Duration(seconds: 1),
    vsync: this,
  );
  _animation1 = Tween<double>(
    begin: 0,
    end: 1,
  ).animate(_controller);
  _animation2 = Tween<double>(
    begin: 0,
    end: 1,
  ).animate(CurvedAnimation(
    parent: _controller,
    curve: Interval(0.5, 1),
  ));
}


Widget build(BuildContext context) {
  return Scaffold(
    body: Center(
      child: AnimatedBuilder(
        animation: _controller,
        builder: (BuildContext context, Widget child) {
          return Transform.scale(
            scale: _animation1.value + _animation2.value,
            child: child,
          );
        },
        child: Container(
          width: 200,
          height: 200,
          color: Colors.red,
        ),
      ),
    ),
    floatingActionButton: FloatingActionButton(
      onPressed: () {
        _controller.forward();
      },
      child: Icon(Icons.play_arrow),
    ),
  );
}

自定义动画组件:

跳动动画,默认先放大再缩小再还原

///  jh_pulse_animation_view.dart
///
///  Created by iotjin on 2023/03/25.
///  description: 跳动动画,先放大再缩小再还原
import 'package:flutter/material.dart';

class JhPulseAnimationView extends StatefulWidget {
  const JhPulseAnimationView({
    Key? key,
    required this.child,
    this.duration = const Duration(milliseconds: 300),
    this.begin = 1.1,
    this.end = 0.9,
    this.isAnimating = false,
    this.onCompleted,
  }) : super(key: key);

  final Widget child; // 点击child自身触发动画(方式一)
  final Duration duration;
  final double begin;
  final double end;
  final bool isAnimating; // 为true触发动画(方式二)
  final Function? onCompleted;

  
  State<JhPulseAnimationView> createState() => _JhPulseAnimationViewState();
}

class _JhPulseAnimationViewState extends State<JhPulseAnimationView> with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  late Animation<double> _animation;

  
  void initState() {
    super.initState();

    _init();
  }

  
  void dispose() {
    _animationController.dispose();

    super.dispose();
  }

  _init() {
    _animationController = AnimationController(vsync: this, duration: widget.duration);
    _animation = TweenSequence<double>([
      TweenSequenceItem(tween: Tween(begin: 1, end: widget.begin), weight: 1),
      TweenSequenceItem(tween: Tween(begin: widget.begin, end: widget.end), weight: 1),
      TweenSequenceItem<double>(tween: Tween(begin: widget.end, end: 1), weight: 1),
    ]).animate(CurvedAnimation(parent: _animationController, curve: Curves.easeIn));
    _startAnimation();
  }

  _startAnimation([isClick = false]) {
    if (widget.isAnimating || isClick) {
      _animationController.forward().then((value) {
        _animationController.reset();
        widget.onCompleted?.call();
      });
    }
  }

  
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => _startAnimation(true),
      child: AnimatedBuilder(
        animation: _animationController,
        builder: (BuildContext context, Widget? child) {
          return Transform.scale(
            scale: _animation.value,
            child: widget.child,
          );
        },
      ),
    );
  }

  
  void didUpdateWidget(covariant JhPulseAnimationView oldWidget) {
    // TODO: implement didUpdateWidget
    super.didUpdateWidget(oldWidget);

    if (widget.isAnimating != oldWidget.isAnimating) {
      _startAnimation();
    }
  }
}

缩放动画,默认放大再还原

///  jh_scale_animation_view.dart
///
///  Created by iotjin on 2023/03/25.
///  description: 缩放动画,默认放大再还原
import 'package:flutter/material.dart';

class JhScaleAnimationView extends StatefulWidget {
  const JhScaleAnimationView({
    Key? key,
    required this.child,
    this.duration = const Duration(milliseconds: 100),
    this.begin = 1.0,
    this.end = 1.1,
    this.isAnimating = false,
    this.onCompleted,
  }) : super(key: key);

  final Widget child; // 点击child自身触发动画(方式一)
  final Duration duration;
  final double begin;
  final double end;
  final bool isAnimating; // 为true触发动画(方式二)
  final Function? onCompleted;

  
  State<JhScaleAnimationView> createState() => _JhScaleAnimationViewState();
}

class _JhScaleAnimationViewState extends State<JhScaleAnimationView> with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  late Animation<double> _animation;

  
  void initState() {
    super.initState();

    _init();
  }

  
  void dispose() {
    _animationController.dispose();

    super.dispose();
  }

  _init() {
    _animationController = AnimationController(vsync: this, duration: widget.duration);
    _animation = Tween<double>(begin: widget.begin, end: widget.end).animate(_animationController)
      ..addListener(() {
        setState(() {});
      })
      ..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          _animationController.reverse();
        } else if (status == AnimationStatus.dismissed) {
          widget.onCompleted?.call();
        }
      });
    _startAnimation();
  }

  _startAnimation([isClick = false]) {
    if (widget.isAnimating || isClick) {
      _animationController.forward();
    }
  }

  
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => _startAnimation(true),
      child: Transform.scale(
        scale: _animation.value,
        child: widget.child,
      ),
    );
  }

  
  void didUpdateWidget(covariant JhScaleAnimationView oldWidget) {
    // TODO: implement didUpdateWidget
    super.didUpdateWidget(oldWidget);

    if (widget.isAnimating != oldWidget.isAnimating) {
      _startAnimation();
    }
  }
}

缩放动画2,默认缩小再还原

///  jh_scale_animation_view2.dart
///
///  Created by iotjin on 2023/03/25.
///  description: 缩放动画,默认缩小再还原
import 'package:flutter/material.dart';

class JhScaleAnimationView2 extends StatefulWidget {
  const JhScaleAnimationView2({
    Key? key,
    required this.child,
    this.duration = const Duration(milliseconds: 100),
    this.begin = 1.0,
    this.end = 0.9,
    this.isAnimating = false,
    this.onCompleted,
  }) : super(key: key);

  final Widget child; // 点击child自身触发动画(方式一)
  final Duration duration;
  final double begin;
  final double end;
  final bool isAnimating; // 为true触发动画(方式二)
  final Function? onCompleted;

  
  State<JhScaleAnimationView2> createState() => _JhScaleAnimationView2State();
}

class _JhScaleAnimationView2State extends State<JhScaleAnimationView2> with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  late Animation<double> _animation;

  
  void initState() {
    super.initState();

    _init();
  }

  
  void dispose() {
    _animationController.dispose();

    super.dispose();
  }

  _init() {
    _animationController = AnimationController(vsync: this, duration: widget.duration);
    _animation = Tween<double>(begin: widget.begin, end: widget.end).animate(_animationController);
    _startAnimation();
  }

  _startAnimation([isClick = false]) {
    if (widget.isAnimating || isClick) {
      _animationController.forward().then((value) {
        _animationController.reverse().then((value) {
          widget.onCompleted?.call();
        });
      });
    }
  }

  
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => _startAnimation(true),
      child: ScaleTransition(
        scale: _animation,
        child: widget.child,
      ),
    );
  }

  
  void didUpdateWidget(covariant JhScaleAnimationView2 oldWidget) {
    // TODO: implement didUpdateWidget
    super.didUpdateWidget(oldWidget);

    if (widget.isAnimating != oldWidget.isAnimating) {
      _startAnimation();
    }
  }
}

抖动(位移)动画,支持上下/左右抖动,默认左右抖动

///  jh_shake_animation_view.dart
///
///  Created by iotjin on 2023/03/25.
///  description: 抖动(位移)动画,支持上下/左右抖动,默认左右抖动
import 'package:flutter/material.dart';

enum ShakeDirection {
  horizontal,
  vertical,
}

class JhShakeAnimationView extends StatefulWidget {
  const JhShakeAnimationView({
    Key? key,
    required this.child,
    this.duration = const Duration(milliseconds: 100),
    this.direction = ShakeDirection.horizontal,
    this.begin = -5,
    this.end = 5,
    this.isAnimating = false,
    this.onCompleted,
  }) : super(key: key);

  final Widget child; // 点击child自身触发动画(方式一)
  final Duration duration;
  final ShakeDirection direction;
  final double begin;
  final double end;
  final bool isAnimating; // 为true触发动画(方式二)
  final Function? onCompleted;

  
  State<JhShakeAnimationView> createState() => _JhShakeAnimationViewState();
}

class _JhShakeAnimationViewState extends State<JhShakeAnimationView> with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  late Animation<double> _animation;

  
  void initState() {
    super.initState();

    _init();
  }

  
  void dispose() {
    _animationController.dispose();

    super.dispose();
  }

  _init() {
    _animationController = AnimationController(vsync: this, duration: widget.duration);
    _animation = TweenSequence<double>([
      TweenSequenceItem(tween: Tween(begin: 0, end: widget.begin), weight: 1),
      TweenSequenceItem(tween: Tween(begin: widget.begin, end: widget.end), weight: 1),
      TweenSequenceItem(tween: Tween(begin: widget.end, end: 0), weight: 1),
    ]).animate(_animationController);
    _startAnimation();
  }

  _startAnimation([isClick = false]) {
    if (widget.isAnimating || isClick) {
      _animationController.forward().then((value) {
        _animationController.reset();
        widget.onCompleted?.call();
      });
    }
  }

  
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => _startAnimation(true),
      child: AnimatedBuilder(
        animation: _animationController,
        builder: (BuildContext context, Widget? child) {
          var x = widget.direction == ShakeDirection.horizontal ? _animation.value : 0.0;
          var y = widget.direction == ShakeDirection.vertical ? _animation.value : 0.0;
          return Transform.translate(
            offset: Offset(x, y),
            child: widget.child,
          );
        },
      ),
    );
  }

  
  void didUpdateWidget(covariant JhShakeAnimationView oldWidget) {
    // TODO: implement didUpdateWidget
    super.didUpdateWidget(oldWidget);

    if (widget.isAnimating != oldWidget.isAnimating) {
      _startAnimation();
    }
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/435906.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

低代码/无代码平台在软件开发中的应用

随着技术的不断发展&#xff0c;软件开发也在不断地进步。低代码/无代码平台已经成为软件开发的一个新的趋势。在这篇文章中&#xff0c;我们将深入探讨低代码/无代码平台在软件开发中的应用&#xff0c;包括它们的优势、如何选择合适的平台以及如何使用这些平台来开发高质量的…

机器学习 CarRentalData数据集分析和预测

介绍数据集 fuelType&#xff1a;燃料类型 rating&#xff1a;评级 renterTripsTaken&#xff1a;租房者出行 reviewCount&#xff1a;审阅计数 location.city&#xff1a;位置.城市 location.country&#xff1a;地点.国家/地区 location.latitude&#xff1a;位置.纬度 loca…

STM32按键实验中连接按键的GPIO管脚是上拉输入还是下拉输入

一、理解 关于STM32按键实验中连接按键的GPIO管脚是配置为上拉输入还是下拉输入的理解&#xff1a; 以江科大自动协教学视频按键输入实验为例&#xff1a; &#xff08;1&#xff09;按键KEY0<——>PE4 按键另一端接GND &#xff08;2&#xff09;按键KEY1<——&…

入门教学 | 快速了解集简云

集简云是一款超级软件连接器,无需开发,无需代码知识就可以轻松打通数百款软件之间的数据连接,构建自动化与智能化的业务流程。通过自动化业务流程,每月可节省企业数百甚至数万小时的人工成本。 集简云是什么? 集简云是一款超级软件连接器,无需开发,无需代码知识,就可以…

在现成的3D打印机上进行实验理论:一种数据孪生的攻击探测框架

在现成的3D打印机上提供了一种DT中攻击探测框架的DT解决方案的实验演示&#xff0c;作为说明性CPMS资源。通过网络安全DT对打印机正常运行、异常运行和攻击三种情况下的实验数据进行收集和分析&#xff0c;得出攻击检测结果。实验装置概述如下图所示。该实验研究是在现实世界设…

刚刚入职Android开发的应届生,该如何走向架构师

相信有不少从事Android开发的朋友&#xff0c;在工作一两年后会陷入一段迷茫期&#xff0c;有的是在工作中遇到了瓶颈&#xff0c;感觉无法突破&#xff1b;有的是想进阶成为架构师&#xff0c;但不知道如何进阶&#xff0c;因此产生了一些烦恼。为此小编在这里分享Android开发…

安卓开发: Compose 中的 Text 文本控件属性详解

Composable fun Text(text: String,modifier: Modifier Modifier,color: Color Color.Unspecified,fontSize: TextUnit TextUnit.Unspecified,fontStyle: FontStyle? null,fontWeight: FontWeight? null,fontFamily: FontFamily? null,letterSpacing: TextUnit TextU…

wps宏编辑器案例1-自定义函数使用

某公司考情和请假系统是2套独立的系统&#xff0c;人资在月底做考勤统计的时候需要把考勤系统导出的考勤信息表和OA请假流程导出的请假信息表进行合并&#xff0c;得出人员真实的考勤情况。比如员工“忠达”在考勤系统全显示缺勤&#xff0c;实际上请假系统里有4天请假&#xf…

16、Web原生组件注入(Servlet、Filter、Listener)

文章目录 1、使用Servlet API2、使用RegistrationBean 【尚硅谷】SpringBoot2零基础入门教程-讲师&#xff1a;雷丰阳 笔记 路还在继续&#xff0c;梦还在期许 1、使用Servlet API ServletComponentScan(basePackages “com.atguigu.admin”) :指定原生Servlet组件都放在那里…

全景天窗式科普数据仓库

数据仓库是一个面向主题的、集成的、随时间变化但信息本身相对稳定的数据集合&#xff0c;用于支持管理决策过程。其本质就是完成从面向业务过程数据的组织管理到面向业务分析数据的组织和管理的转变过程&#xff0c;也是商业智能BI中数据仓库的主要作用。 数据仓库 - 派可数据…

Spring Boot 定时任务

Spring Boot 提供了方便的注解来实现定时任务。下面是定时任务注解的详细教程&#xff1a; 一、添加依赖 要使用 Spring Boot 的定时任务注解&#xff0c;首先需要在项目中确认已添加过spring-boot-starter的依赖。 <dependency><groupId>org.springframework.b…

【youcans的深度学习 D01】PyTorch例程:从极简线性模型开始

欢迎关注『youcans的深度学习』系列 【youcans的深度学习 D01】PyTorch 例程&#xff1a;从极简线性模型开始 1. PyTorch 建模的基本步骤2. 线性模型的结构3. 建立 PyTorch 线性模型3.1 准备数据集3.2 定义线性模型类3.3 建立一个线性模型3.4 模型训练3.5 模型推断 4. PyTorch …

java-处理xml格式数据

处理xml格式数据 前言一、java处理xml格式数据1、 生成XML格式数据2、 解析XML格式数据 二、问题三、常用类及方法介绍 前言 dom4j是java中的XML API&#xff0c;性能优异、功能强大、开放源代码。 也是所有解析XML文件方法中最常用的&#xff01; 一、java处理xml格式数据 …

榜单发布 新能源乘用车OBC赛道进入转型升级周期

新能源汽车尤其是纯电动汽车市场的快速普及&#xff0c;也带动一批相关核心零部件厂商做大做强。比如&#xff0c;以车载充电机OBC及集成电源行业为例&#xff0c;威迈斯、富特科技等数家公司正在冲刺IPO。 目前&#xff0c;车载电源领域产品主要分为三种&#xff1a;一是单一…

步入AIGC时代,展望人工智能发展

步入AIGC时代&#xff0c;展望人工智能发展 0. 前言1. 步入 AIGC 时代1.1 人工智能简介1.2 AIGC 简介1.3 AIGC 发展与应用 2. CSIG 企业行——走进合合信息2.1 活动介绍2.2 走进合合信息 3. 文档图像处理中的底层视觉技术3.1 什么是底层视觉3.2 智能图像处理技术3.3 智能图像处…

消息中间件RabbitMQ---概述和概念 【一】

1、概述 1、大多应用中&#xff0c;可通过消息服务中间件来提升系统异步通信、扩展解耦能力 2、消息服务中两个重要概念&#xff1a; 消息代理&#xff08;message broker&#xff09;和目的地&#xff08;destination&#xff09; 当消息发送者发送消息以后&#xff0c;将由…

C语言中数据结构——顺序表

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C &#x1f525;座右铭&#xff1a;“不要等到什么都没有了&#xff0c;才下…

java多线程详细讲解 线程的创建、线程的状态、synchronized锁、Volatile关键字、和cas锁(自旋锁 乐观锁 无锁)

java多线程详细讲解 线程的创建、线程的状态、synchronized锁、Volatile关键字、和cas锁&#xff08;自旋锁 乐观锁 无锁&#xff09; 一、线程的概念二、创建线程的三种方式三、线程方法Sleep、Yield、Join四、线程的执行状态五、synchronized关键字1.为什么要上锁?2.锁定的内…

SDL初识(1)

简介 SDL(Simple DirectMedia Layer) 是一个跨平台开发库&#xff0c;旨在通过 OpenGL 和 Direct3D 提供对音频、键盘、鼠标、操纵杆和图形硬件的低级访问。 SDL 支持 Windows、Mac OS X、Linux、iOS 和 Android。可以在源代码中找到对其他平台的支持。SDL 是用 C 语言编写的…

JavaScript【六】JavaScript中的字符串(String)

文章目录 &#x1f31f;前言&#x1f31f;字符串(String)&#x1f31f;单引号和双引号的区别&#x1f31f;属性&#x1f31f; length :字符串的长度 &#x1f31f; 方法&#x1f31f; str.charAt(index);&#x1f31f; str.charCodeAt(index);&#x1f31f; String.fromCharCod…