为了满足我们自身的开发需求,很多时候就需要我们自定动手制作东西,也就是所谓的自定义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: <Widget>[
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: <Widget>[
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: <Widget>[
new Padding(
padding: const EdgeInsets.all(10.0),
child: new Stack(
alignment: AlignmentDirectional.centerEnd,
children: <Widget>[
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 = <Widget>[];
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