我有三个页面(用户应执行三个步骤来进行身份验证)。每个页面都包含一个表单和一个Submit RawMaterialButton,以从服务器获取响应。目前,我正在使用materialpageroute在页面之间导航。我想使用包含所有三个页面的垂直页面浏览量,并具有圆形指示器,并使用页面浏览量的动画而不是实质页面路线在这三个页面之间导航。 这是我的页面之一:
class AuthOnePage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _AuthOnePageState();
}
}
class _AuthOnePageState extends State<AuthOnePage> {
final Map<String, dynamic> _formData = {
'phone': '',
};
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
Widget _buildPhoneTextField() {
return Container(
width: MediaQuery.of(context).size.width / 1.05,
height: MediaQuery.of(context).size.height / 16,
decoration: BoxDecoration(
border: Border.all(color: CustomColors()),
color: Colors.transparent,
borderRadius: new BorderRadius.all(
const Radius.circular(40.0),
),
),
child: Row(
children: <Widget>[
Text(
' +98',
style: TextStyle(fontSize: 22.0 , color: CustomColors().khakestari),
),
SizedBox(
width: 1.0,
),
VerticalDivider(
indent: 8.0,
),
SizedBox(width: 4.0),
Expanded(
child: TextFormField(
textDirection: TextDirection.rtl,
textAlign: TextAlign.end,
autofocus: true,
style: TextStyle(fontSize: 22.0 , color: CustomColors().khakestari),
decoration: InputDecoration(
filled: false,
isDense: true,
errorStyle: TextStyle(fontSize: 15.0 ,),
hintText: '',
hintStyle: TextStyle( fontSize: 22.0),
border: InputBorder.none,
),
keyboardType: TextInputType.phone,
validator: (String value) {
if (value.isEmpty ||
value.length < 10 ||
!RegExp(r"^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\./0-9]*$")
.hasMatch(value)) {
return '';
}
},
onSaved: (String value) {
_formData['phone'] = value;
},
),
),
Container(
width: 50,
height: 50,
child: Icon(
Icons.phone_iphone,
color: CustomColors(),
),
),
],
),
);
}
void _submitForm(Function authenticateFirst) async {
if (!_formKey.currentState.validate()) {
return;
}
_formKey.currentState.save();
Map<String, dynamic> successInformation;
successInformation = await authenticateFirst(_formData['phone']);
if (successInformation['success']) {
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (BuildContext context) {
return AuthTwoPage();
}));
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(''),
content: Text(''),
actions: <Widget>[
FlatButton(
child: Text(''),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
},
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: Container(
margin: EdgeInsets.all(10.0),
child: Container(
padding:
EdgeInsets.only(top: MediaQuery.of(context).size.height / 4.5),
child: Column(
children: <Widget>[
Center(
child: Text(
'',
style:
TextStyle(fontSize: 40.0, fontFamily: 'IrYek'),
)),
SizedBox(height: MediaQuery.of(context).size.height / 7),
Form(
key: _formKey,
child: Column(
children: <Widget>[
_buildPhoneTextField(),
SizedBox(
height: 50.0,
),
ScopedModelDescendant<MainModel>(
builder: (BuildContext context, Widget child,
MainModel model) {
return model.isLoading
? CircularProgressIndicator()
: RawMaterialButton(
highlightElevation: 40,
onPressed: () =>
_submitForm(model.authenticateFirst),
splashColor: Colors.white,
shape: StadiumBorder(),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: <Color>[
Color(0xff4b66ea),
Color(0xff4b66ea),
Color(0xff4b66ea),
Colors.blue
],
),
boxShadow: [
BoxShadow(
color: Colors.black26,
offset: Offset(0.0, 1.5),
blurRadius: 1.5,
),
],
borderRadius:
BorderRadius.circular(40)),
width: MediaQuery.of(context).size.width /
1.05,
height:
MediaQuery.of(context).size.height /
15,
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(
vertical: 8.0, horizontal: 20.0),
child: Text(
'',
style: TextStyle(
fontFamily: 'IrBold',
color: Colors.white,
fontSize: 20),
),
),
),
),
);
},
),
],
),
)
],
),
),
),
),
);
}
这是到目前为止我的综合浏览量代码:
import 'package:flutter/material.dart';
import 'dart:math';
import 'package:flutter/foundation.dart';
import './authone.dart';
import './authtwo.dart';
import './auththree.dart';
/// An indicator showing the currently selected page of a PageController
class DotsIndicator extends AnimatedWidget {
DotsIndicator({
this.controller,
}) : super(listenable: controller);
/// The PageController that this DotsIndicator is representing.
final PageController controller;
/// The number of items managed by the PageController
final int itemCount =3 ;
/// The color of the dots.
///
/// Defaults to `Colors.white`.
final Color color = Colors.amber[200];
// The base size of the dots
static const double _kDotSize = 8.0;
// The increase in the size of the selected dot
static const double _kMaxZoom = 2.0;
// The distance between the center of each dot
static const double _kDotSpacing = 25.0;
Widget _buildDot(int index) {
double selectedness = Curves.easeOut.transform(
max(
0.0,
1.0 - ((controller.page ?? controller.initialPage) - index).abs(),
),
);
double zoom = 1.0 + (_kMaxZoom - 1.0) * selectedness;
return new Container(
width: _kDotSpacing,
child: new Center(
child: new Material(
color: color,
type: MaterialType.circle,
child: new Container(
width: _kDotSize * zoom,
height: _kDotSize * zoom,
),
),
),
);
}
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: new List<Widget>.generate(itemCount, _buildDot),
);
}
}
class AuthCollectionPage extends StatefulWidget {
@override
State createState() => new AuthCollectionPageState();
}
class AuthCollectionPageState extends State<AuthCollectionPage> {
final _controller = new PageController(viewportFraction: 0.5);
static const _kDuration = const Duration(milliseconds: 300);
static const _kCurve = Curves.ease;
final _kArrowColor = Colors.black.withOpacity(0.8);
final List<Widget> _pages = <Widget>[
AuthOnePage(),
AuthTwoPage(),
AuthThreePage()
];
Widget _buildPageItem(BuildContext context, int index) {
return new Page(page: _pages[index], idx: index);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new IconTheme(
data: new IconThemeData(color: _kArrowColor),
child: new Stack(
children: <Widget>[
new PageView.builder(
physics: new AlwaysScrollableScrollPhysics(),
controller: _controller,
itemCount: _pages.length,
itemBuilder: (BuildContext context, int index) {
return _buildPageItem(context, index % _pages.length);
},
),
new Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: new Container(
color: Colors.grey[800].withOpacity(0.5),
padding: const EdgeInsets.all(20.0),
child: new Center(
child: new DotsIndicator(
controller: _controller,
itemCount: _pages.length,
onPageSelected: (int page) {
_controller.animateToPage(
page,
duration: _kDuration,
curve: _kCurve,
);
},
),
),
),
),
],
),
),
);
}
}
class Page extends StatelessWidget {
final page;
final idx;
Page({
@required this.page,
@required this.idx,
});
onTap() {
print("${this.idx} selected.");
}
@override
Widget build(BuildContext context) {
return new Padding(
padding: const EdgeInsets.all(8.0),
child: new Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new Container(
height: 200.0,
child: new Card(
child: new Stack(
fit: StackFit.expand,
children: <Widget>[
this.page,
new Material(
type: MaterialType.transparency,
child: new InkWell(onTap: this.onTap),
),
],
),
),
),
],
),
);
}
}