美文网首页
Flutter开发上手,自定义组件 Button Demo

Flutter开发上手,自定义组件 Button Demo

作者: 程就人生 | 来源:发表于2021-07-10 22:33 被阅读0次

在实际开发中,如果 Flutter 现有的组件不能满足我们的需求,那么就需要自定义组件。Flutter中自定义组件有三种方式:通过组合其它组件、自绘和实现RenderObject。先来个简单的,组合其他组件,实现一个自定义按钮组件。

业务需求:
1. 按钮颜色渐变;
2. 按钮可设置圆角;
3. 按钮点击时,按钮颜色有涟漪效果;
4. 实现点击事件,包括状态保持;

第一步,自定义按钮组件;

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
/// 自定义按钮
class CustomButton extends StatelessWidget{
  // 渐变色设置
  final List<Color>? colors;
  // 宽度设置
  final double? width;
  // 高度设置
  final double? height;
  // 子组件
  final Widget child;
  /// 触发回调
  final GestureTapCallback? onTap;
  //圆角设置
  final BorderRadius? borderRadius;
  /// 构造方法
  CustomButton({this.colors, this.width, this.height,this.onTap, this.borderRadius,required this.child});

  @override
  Widget build(BuildContext context) {
    //通过context获取主题
    ThemeData theme = Theme.of(context);
    // 如果 colors 为null时,使用上下文中的主颜色,colors时,使用系统主色
    List<Color> _colors = colors ?? [theme.primaryColor,theme.primaryColorDark];

    // 构建装饰类容器
    DecoratedBox decoratedBox = DecoratedBox(
      decoration: BoxDecoration(
        gradient: LinearGradient(colors:_colors),
        borderRadius: borderRadius,
      ),
      child: Material(
        type: MaterialType.transparency,
        // 水波纹效果
        child: InkWell(
          splashColor: colors!.last,      
          highlightColor: Colors.transparent,
          // 点击事件
          onTap: onTap,
          // 约束盒子
          child: ConstrainedBox(
            constraints: BoxConstraints.tightFor(height: height,width: width),
            // 布局方位类
            child: Center(
              // 设置边距
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                // 设置样式
                child: DefaultTextStyle(
                  style: TextStyle(fontWeight: FontWeight.bold),
                  child: child,
                ),
              ),
            ),
          ),
        ),
      ),
    );

    // 如果组合控件中没有点击事件,则需要自己实现点击回调事件
    // final Map<Type, GestureRecognizerFactory> gestures = <Type, GestureRecognizerFactory>{};
    // // 如果传递回调事件时,回调事件的关键代码
    // if(onTap != null){
    //   gestures[TapGestureRecognizer] = GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
    //         () => TapGestureRecognizer(debugOwner: this),
    //         (TapGestureRecognizer instance) {
    //       instance
    //         ..onTap = onTap;
    //     },
    //   );
    // }
    // // 使用 RawGestureDetector 构造控件,RawGestureDetector是有状态的组件
    // return RawGestureDetector(
    //        gestures: gestures,
    //        child: decoratedBox,
    //      );

    return decoratedBox;
  }
}

备注:

  1. 在这一组组合组件中,既有无状态组件(InkWell),也有有状态组件(Material),还有实现RenderObject类的组件,ConstrainedBox、DecoratedBox类间接继承了RenderObject类。
  2. 在处理点击事件时,刚开始不知道把点击事件放在哪个控件下,查看GestureDetector 源码写了注释掉的那段代码,后来发现 InkWell 类中已经包含了 onTap事件,就把那一段代码注释掉了。

第二步,调用自定义组件;
功能说明:使用自定义按钮,传递高度、宽度、颜色组等参数,并在点击按钮时,记录点击次数。

import 'package:flutter/material.dart';
import 'CustomButton.dart';
//调用自定义组件
class CustomWidgetRoute extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    return _CustomWidgetRouteState();
  }
}
class _CustomWidgetRouteState extends State<CustomWidgetRoute>{
  int _counter = 0;
  void doClick(){
    setState(() {
      debugPrint("组合组件被点击了");
      _counter++;
    });
  }
  @override
  Widget build(BuildContext context) {
    return Center(
              child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                  Text(
                     '$_counter',
                      style: Theme.of(context).textTheme.headline4,
                  ),
                  CustomButton(
                      colors: [Colors.lime, Colors.green],
                      width: 200,
                      height: 50,
                      child: Text("自定义按钮"),
                      borderRadius: BorderRadius.circular(20),
                      onTap: doClick,
                      ),
                  ],
              ),
        );
  }
}

第三步,加入主程序,运行代码;

import 'package:flutter/material.dart';
import 'CustomWidgetRoute.dart';
void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text("welocom to flutter"),
        ),
        body: CustomWidgetRoute(),
      ),
    );
  }
}
运行结果图

相关文章

网友评论

      本文标题:Flutter开发上手,自定义组件 Button Demo

      本文链接:https://www.haomeiwen.com/subject/akfhpltx.html