Flutter开发之自定义view,widget

为了满足我们自身的开发需求,很多时候就需要我们自定动手制作东西,也就是所谓的自定义view,那么我们一起学习下flutter的自定义view吧

本人理解flutter的自定义view可以归为两类:
1,已有控件(widget)的继承,组合
2,自定义绘制widget,也就是利用paint,cavans等进行绘制视图。

1,先来示例第一种吧

我们做一个自定义的dialog,这个dialog是继承原生自带的Dialog,并且组合其他的控件一起的。

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

 
class TestMessageDialog extends Dialog {
  BuildContext mContext;
  String title;
  String message;
  String negativeText;
  String positiveText;
  Function onCloseEvent;
  Function onPositivePressEvent;

  TestMessageDialog({
    Key key,
    @required this.title,
    @required this.message,
    this.negativeText,
    this.positiveText,
    this.onPositivePressEvent,
    @required this.onCloseEvent,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    mContext=context;
    return GestureDetector(
        onTap: () {
          Navigator.pop(context);
        },
        child: WillPopScope(
          onWillPop: () {
            _onNavigationClickEvent();
            return Future.value(false);
          },
          child: Material(
            color: Colors.transparent,

            child: Stack(
              fit: StackFit.expand,
              children: [
                GestureDetector(onTap: _onNavigationClickEvent),
                _buildContentView(), //构建具体的对话框布局内容
              ],
            ),
          ),
        ));

  }

  void _onNavigationClickEvent(){

    Navigator.pop(mContext);
  }
  Widget _buildContentView(){
    return new Padding(
      padding: const EdgeInsets.all(15.0),
      child: new Material(
        type: MaterialType.transparency,
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            new Container(
              decoration: ShapeDecoration(
                color: Color(0xffffffff),
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.all(
                    Radius.circular(8.0),
                  ),
                ),
              ),
              margin: const EdgeInsets.all(12.0),
              child: new Column(
                children: [
                  new Padding(
                    padding: const EdgeInsets.all(10.0),
                    child: new Stack(
                      alignment: AlignmentDirectional.centerEnd,
                      children: [
                        new Center(
                          child: new Text(
                            title,
                            style: new TextStyle(
                              fontSize: 19.0,
                            ),
                          ),
                        ),
                        new GestureDetector(
                          onTap: this.onCloseEvent,
                          child: new Padding(
                            padding: const EdgeInsets.all(5.0),
                            child: new Icon(
                              Icons.close,
                              color: Color(0xffe0e0e0),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  new Container(
                    color: Color(0xffe0e0e0),
                    height: 1.0,
                  ),
                  new Container(
                    constraints: BoxConstraints(minHeight: 180.0),
                    child: new Padding(
                      padding: const EdgeInsets.all(12.0),
                      child: new IntrinsicHeight(
                        child: new Text(
                          message,
                          style: TextStyle(fontSize: 16.0),
                        ),
                      ),
                    ),
                  ),
                  this._buildBottomButtonGroup(),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }


  Widget _buildBottomButtonGroup() {
    var widgets = [];
    if (negativeText != null && negativeText.isNotEmpty) widgets.add(_buildBottomCancelButton());
    if (positiveText != null && positiveText.isNotEmpty) widgets.add(_buildBottomPositiveButton());
    return new Flex(
      direction: Axis.horizontal,
      children: widgets,
    );
  }

  Widget _buildBottomCancelButton() {
    return new Flexible(
      fit: FlexFit.tight,
      child: new FlatButton(
        onPressed: onCloseEvent,
        child: new Text(
          negativeText,
          style: TextStyle(
            fontSize: 16.0,
          ),
        ),
      ),
    );
  }

  Widget _buildBottomPositiveButton() {
    return new Flexible(
      fit: FlexFit.tight,
      child: new FlatButton(
        onPressed: onPositivePressEvent,
        child: new Text(
          positiveText,
          style: TextStyle(
            color: Color(Colors.teal.value),
            fontSize: 16.0,
          ),
        ),
      ),
    );
  }
} 

上面的自定义dialog就是继承原生Dialog之后结合其他控件使用的一种典型例子,为了满足需求你还可以加个回调函数final Function callback; 修改之后的回掉函数,增加dialog操作之后回调给页面。具体的一步步操作就好了。

2,下面介绍第二种,纯手工制作的控件(自绘)

我们就来个简单的例子。
最近看了别人博客跟着做了个小球下落的功能,那就看个自定义小球的例子吧

import 'dart:ui';

import 'package:flutter/material.dart';

///小球信息描述类
class Ball {
  double aX; //加速度
  double aY; //加速度Y
  double vX; //速度X
  double vY; //速度Y
  double x; //点位X
  double y; //点位Y
  Color color; //颜色
  double r;//小球半径

  Ball({this.x=0, this.y=0, this.color, this.r=10,
    this.aX=0, this.aY=0, this.vX=0, this.vY=0});
}

///画板Painter
class RunBallView extends CustomPainter {
  Ball _ball; //小球
  Rect _area;//运动区域
  Paint mPaint; //主画笔
  Paint bgPaint; //背景画笔

  RunBallView(this._ball,this._area) {
    mPaint = new Paint();
    bgPaint = new Paint()..color = Color.fromARGB(148, 198, 246, 248);
  }

  @override
  void paint(Canvas canvas, Size size) {
    canvas.drawRect(_area, bgPaint);
    _drawBall(canvas, _ball);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }

  ///使用[canvas] 绘制某个[ball]
  void _drawBall(Canvas canvas, Ball ball) {
    canvas.drawCircle(
        Offset(ball.x, ball.y), ball.r, mPaint..color = ball.color);
  }
}

var _area= Rect.fromLTRB(0+40.0,0+200.0,280+40.0,200+200.0);
var _ball = Ball(color: Colors.blueAccent, r: 10,x: 40.0+140,y:200.0+100);
 
var child = Scaffold(
  body: CustomPaint(
    painter: RunBallView(_ball,_area),
  ),
);

这个自身根据需要作出自定义的小球,然后再加上算法和函数就可以随心地做你想要的东西了。

这一篇章写得比较粗糙,本来打算做一个自定义的下雪动画的,下次再上代码介绍吧,先理解好先。
也可以参考下面文章理解:
https://book.flutterchina.club/chapter10/intro.html

你可能感兴趣的:(Flutter开发之自定义view,widget)