為了滿足我們自身的開發(fā)需求,很多時候就需要我們自定動手制作東西,也就是所謂的自定義view,那么我們一起學(xué)習(xí)下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(), //構(gòu)建具體的對話框布局內(nèi)容
],
),
),
));
}
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之后結(jié)合其他控件使用的一種典型例子,為了滿足需求你還可以加個回調(diào)函數(shù)final Function callback; 修改之后的回掉函數(shù),增加dialog操作之后回調(diào)給頁面。具體的一步步操作就好了。
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;//運動區(qū)域
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),
),
);
這個自身根據(jù)需要作出自定義的小球,然后再加上算法和函數(shù)就可以隨心地做你想要的東西了。
這一篇章寫得比較粗糙,本來打算做一個自定義的下雪動畫的,下次再上代碼介紹吧,先理解好先。
也可以參考下面文章理解:
https://book.flutterchina.club/chapter10/intro.html