一统天下 flutter

Posted webabcd - 专注于 flutter, android

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一统天下 flutter相关的知识,希望对你有一定的参考价值。

一统天下 flutter - widget 自定义: 通过组合多个 Widget 的方式实现自定义组件

源码 https://github.com/webabcd/flutter_demo
作者 webabcd

一统天下 flutter - widget 自定义: 通过组合多个 Widget 的方式实现自定义组件

示例如下:

lib\\widget\\custom\\custom_widget.dart

/*
 * 通过组合多个 Widget 的方式实现自定义组件
 */

import \'dart:math\';

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

import \'../../helper.dart\';

class CustomWidgetDemo extends StatefulWidget 
  const CustomWidgetDemo(Key? key) : super(key: key);

  @override
  _CustomWidgetDemoState createState() => _CustomWidgetDemoState();


class _CustomWidgetDemoState extends State<CustomWidgetDemo> 

  double _angle = .0;

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(title: const Text("title"),),
      backgroundColor: Colors.orange,
      body: Column(
        children: [
          /// 通过继承已有 Widget 的方式实现自定义 Widget
          const _MyText("_MyText"),

          /// 通过继承 StatelessWidget 的方式实现自定义的无状态组件
          _GradientButton(
            colors: const [Colors.red, Colors.green],
            borderRadius: BorderRadius.circular(10),
            width: 300,
            height: 50,
            child: const Text("_GradientButton"),
            onPressed: () 
              setState(() 
                _angle += pi / 2;
              );
            ,
          ),

          /// 通过继承 StatefulWidget 的方式实现自定义的有状态组件
          _RotationAnimationBox(
            angle: _angle,
            duration: 500,
            child: const MyText("_RotationAnimationBox"),
          ),
        ],
      ),
    );
  


/// 通过继承已有 Widget 的方式实现自定义 Widget
/// 下面的示例用于实现一个自定义的 Text 组件,其默认文字大小 24,颜色白色,无下划线
class _MyText extends Text 
  const _MyText(super.data) : super(
    style: const TextStyle(
      fontSize: 24.0,
      color: Colors.white,
      decoration: TextDecoration.none,
    ),
  );


/// 通过继承 StatelessWidget 的方式实现自定义的无状态组件
/// 下面的示例用于实现一个支持渐变背景色的按钮组件
class _GradientButton extends StatelessWidget 
  const _GradientButton(
    this.colors,        /// 渐变色
    this.borderRadius,
    this.width,
    this.height,
    required this.onPressed,
    required this.child,
  );
  final List<Color>? colors;
  final BorderRadius? borderRadius;
  final double? width;
  final double? height;
  final GestureTapCallback? onPressed;
  final Widget child;

  @override
  Widget build(BuildContext context) 
    ThemeData theme = Theme.of(context);
    List<Color> _colors = colors ?? [theme.primaryColor];
    return DecoratedBox(
      decoration: BoxDecoration(
        gradient: LinearGradient(colors: _colors),
        borderRadius: borderRadius,
      ),
      child: Material(
        type: MaterialType.transparency,
        child: InkWell(
          borderRadius: borderRadius,
          onTap: onPressed,
          child: ConstrainedBox(
            constraints: BoxConstraints.tightFor(height: height, width: width),
            child: Center(
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: DefaultTextStyle(
                  style: const TextStyle(fontWeight: FontWeight.bold),
                  child: child,
                ),
              ),
            ),
          ),
        ),
      ),
    );
  


/// 通过继承 StatefulWidget 的方式实现自定义的有状态组件
/// 下面的示例用于实现一个支持旋转动画的组件
class _RotationAnimationBox extends StatefulWidget 
  const _RotationAnimationBox(
    this.angle = .0,      /// 目标旋转弧度
    this.duration = 200,  /// 从当前弧度旋转到目标旋转弧度的动画时长
    required this.child
  );
  final double angle;
  final int duration;
  final Widget child;

  @override
  _RotationAnimationBoxState createState() => _RotationAnimationBoxState();

class _RotationAnimationBoxState extends State<_RotationAnimationBox> with SingleTickerProviderStateMixin 
  late AnimationController _controller;

  @override
  void initState() 
    super.initState();
    _controller = AnimationController(vsync: this, lowerBound: -double.infinity, upperBound: double.infinity);
    _controller.value = widget.angle;
  

  @override
  void dispose() 
    _controller.dispose();
    super.dispose();
  

  @override
  Widget build(BuildContext context) 
    return RotationTransition(
      /// turns 的意思是旋转的圈数,也就是说 turns = angle / (2 * pi)
      turns: _controller,
      child: widget.child,
    );
  

  /// 当父组件重绘时
  @override
  void didUpdateWidget(_RotationAnimationBox oldWidget) 
    super.didUpdateWidget(oldWidget);

    /// 如果 _RotationAnimationBox 的 angle 发生变化了则启动动画
    if (oldWidget.angle != widget.angle) 
      /// _controller 会从当前值动画到 widget.angle / (2 * pi)
      _controller.animateTo(widget.angle / (2 * pi), duration: Duration(milliseconds: widget.duration), curve: Curves.ease);
    
  

源码 https://github.com/webabcd/flutter_demo
作者 webabcd

flutter与compose的爱恨情仇

点击上方蓝字关注我,知识会给你力量

话说天下大势,分久必合,合久必分,自Flutter举义起,已两年有余。

然天下苦客户端久矣,一个需求不论是Android还是iOS,各端的实现都不一样,开发难度也不一样,实现效果也不一样,开发时间double,bugfix也是double,所以,跨端的开发应运而生,从H5的探索到RN的探索,这些跨平台方案始终都没逃出原生开发的桎梏,直到Flutter的出现,让跨平台开发进入了全新的时代,自渲染引擎的跨平台方案,打开了跨平台的阳光大道,从目前来看,Flutter已经算是成功了。

有人的地方就有卷王。

同样的Google,内部又孵化出了Compose,从表现上来说,Compose和Flutter是非常接近的,不能说完全一样,毕竟还是有差别的。但整体都是申明式编程,这点已经是当前最热的编程趋势了,十年河东,十年河西。

那为啥Google内部也要这么卷呢?

究其原因,还是因为团队不同,Flutter诞生于Chrome团队,是一帮做Web的开发做的跨平台框架,从最开始的设计初衷,就是指向了跨平台这条路,而Compose,则是诞生于Android团队,是为了解决当前View的架构体系不能再继续适应申明式编程的范式而做出的重构。

所以,从这一点上来看,Flutter身上,实际带着很多前端的影子,从布局方式到代码风格,都是浓浓的前端风,而且Flutter的工作重心在于跨平台,所以在各端的细节打磨上还有一些不足,不论是状态管理还是数据流,Flutter的官方解决方案还没有形成统一,但是Flutter的自渲染引擎,让它的绘制功夫成了一绝,不用受限于原生的绘制,可以让渲染做到随心所欲,所以,如果你的App是一个偏向于强展示性的应用,那么Flutter可以让你的App更加富有表现力。

但Flutter的问题也很明显,由于它的独立性,这就导致了混编的问题会非常多,Flutter嵌入原生App后,资源、图片的交互和共享,就成了比较麻烦的问题,可以说,Flutter目前的核心应用场景是独立的跨平台App,而非混编的App。

那么Compose呢?

从时间点上来看,Compose的诞生晚于Flutter,但Compose充分吸收了Flutter的各种优点,如果你两种框架都有使用过,你就可以在它们身上同时发现彼此的影子。

对于Compose来说,它的首要任务不是解决跨平台问题,而是提高原生App的开发效率,推翻了原有的命令式View体系,使用Compose提供了一整套的申明式UI架构。

这样一来,格局就打开了,先不用纠结跨平台的各种问题,我就先把Android搞搞好,所以,Compose可以无缝和现有原生App混编,而且不能叫混编,因为它本身就是原生,只不过是利用一种框架,实现了新的编程语法,这种申明式的语法,完全放弃了xml的布局方式,这样一来,什么ViewBinding,DataBinding都成为了过去式,退一步,海阔天空。再借助Kotlin愈发成熟的语言机制,大量的语法糖和编译器黑科技,让Compose如虎添翼,所以从一开始,Compose在原生这条路上,就领先了Flutter一个车位,不论是协程还是Flow,还是JetPack组件,可以无缝提供给Compose,以至于状态管理、数据流的问题迎刃而解,特别是ConstraintLayout和MotionLayout的Compose化,让原生的布局编程相比Flutter有了质的飞跃。

那么问题来了,我该用哪个?

打工仔的世界里,哪里有单选题。

扶我起来,我还能学

当然,大家对待这些层出不穷的新技术,应该抱有这样的态度——海纳百川、追求卓越、开明睿智、大气谦和。

首先,Flutter和Compose并不冲突,我是原生开发,但并不妨碍我学习Flutter,我的开源项目Flutter Dojo,https://github.com/xuyisheng/flutter_dojo ,也吸引了上千人加入我的Flutter修仙群,学了Flutter,再看Compose,很快就能上手,这叫什么,殊途同归。我们对待这些新技术一定要抱着谦卑的学习心态,了解它的使用,了解它的设计思路,正所谓海纳百川,有容乃大。

其次,技术不是单选题,但是却有优先级。

  • 如果你是全新的项目,希望快速开发,并且支持多端跨平台,那么Flutter绝对是你目前最好的选择。

  • 如果你是原生开发,需要提高开发效率,那么Compose和kotlin,绝对是你逃不掉的技术壁垒。

向大家推荐下我的网站 https://xuyisheng.top/  点击原文一键直达

专注 Android-Kotlin-Flutter 欢迎大家访问

往期推荐

本文原创公众号:群英传,授权转载请联系微信(Tomcat_xu),授权后,请在原创发表24小时后转载。

< END >

作者:徐宜生

更文不易,点个“三连”支持一下????

以上是关于一统天下 flutter的主要内容,如果未能解决你的问题,请参考以下文章

一统天下 flutter

一统天下 flutter

一统天下 flutter

一统天下 flutter

一统天下 flutter

一「表」走天下,Flutter瀑布流及通用列表解决方案