我正试图实现一种在Flutter中刷卡时触发功能的方法。我正在使用Flutter_Swiper ( )构建一个具有堆叠卡布局的用户界面。https:/pub.devpackagesflutter_swiper。)
我尝试过同时使用GestureDetector和SwipeDetector (https:/pub.devpackagesswipedetector。)但这两个结果都会导致Flutter_Swiper断裂。
有谁知道使用Flutter_Swiper触发一个函数的方法吗?
你可以复制粘贴运行完整的代码下面 你可以调用函数在 onIndexChanged
代码段
return Swiper(
onTap: (int index) {
...
customLayoutOption: customLayoutOption,
fade: _fade,
index: _currentIndex,
onIndexChanged: (int index) {
setState(() {
_currentIndex = index;
print(_currentIndex);
});
},
工作示范
产出
I/flutter ( 4664): 1
I/flutter ( 4664): 2
全码
import 'package:flutter/material.dart';
import 'package:flutter_page_indicator/flutter_page_indicator.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
import 'package:flutter/cupertino.dart';
class FormWidget extends StatelessWidget {
final String label;
final Widget child;
FormWidget({this.label, this.child});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(5.0),
child: Row(
children: <Widget>[
Text(label, style: TextStyle(fontSize: 14.0)),
Expanded(
child: Align(alignment: Alignment.centerRight, child: child))
],
));
}
}
class FormSelect<T> extends StatefulWidget {
final String placeholder;
final ValueChanged<T> valueChanged;
final List<dynamic> values;
final dynamic value;
FormSelect({this.placeholder, this.valueChanged, this.value, this.values});
@override
State<StatefulWidget> createState() {
return _FormSelectState();
}
}
class _FormSelectState extends State<FormSelect> {
int _selectedIndex = 0;
@override
void initState() {
for (int i = 0, c = widget.values.length; i < c; ++i) {
if (widget.values[i] == widget.value) {
_selectedIndex = i;
break;
}
}
super.initState();
}
@override
Widget build(BuildContext context) {
String placeholder = widget.placeholder;
List<dynamic> values = widget.values;
return Container(
child: InkWell(
child: Text(_selectedIndex < 0
? placeholder
: values[_selectedIndex].toString()),
onTap: () {
_selectedIndex = 0;
showBottomSheet(
context: context,
builder: (BuildContext context) {
return SizedBox(
height: values.length * 30.0 + 200.0,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(
height: values.length * 30.0 + 70.0,
child: CupertinoPicker(
itemExtent: 30.0,
children: values.map((dynamic value) {
return Text(value.toString());
}).toList(),
onSelectedItemChanged: (int index) {
_selectedIndex = index;
},
),
),
Center(
child: RaisedButton(
onPressed: () {
if (_selectedIndex >= 0) {
widget
.valueChanged(widget.values[_selectedIndex]);
}
setState(() {});
Navigator.of(context).pop();
},
child: Text("ok"),
),
)
],
),
);
});
},
),
);
}
}
class NumberPad extends StatelessWidget {
final num number;
final num step;
final num max;
final num min;
final ValueChanged<num> onChangeValue;
NumberPad({this.number, this.step, this.onChangeValue, this.max, this.min});
void onAdd() {
onChangeValue(number + step > max ? max : number + step);
}
void onSub() {
onChangeValue(number - step < min ? min : number - step);
}
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconButton(icon: Icon(Icons.exposure_neg_1), onPressed: onSub),
Text(
number is int ? number.toString() : number.toStringAsFixed(1),
style: TextStyle(fontSize: 14.0),
),
IconButton(icon: Icon(Icons.exposure_plus_1), onPressed: onAdd)
],
);
}
}
const List<String> images = [
"https://picsum.photos/250?image=9",
"https://picsum.photos/250?image=10",
"https://picsum.photos/250?image=11",
];
class ExampleCustom extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _ExampleCustomState();
}
}
class _ExampleCustomState extends State<ExampleCustom> {
//properties want to custom
int _itemCount;
bool _loop;
bool _autoplay;
int _autoplayDely;
double _padding;
bool _outer;
double _radius;
double _viewportFraction;
SwiperLayout _layout;
int _currentIndex;
double _scale;
Axis _scrollDirection;
Curve _curve;
double _fade;
bool _autoplayDisableOnInteraction;
CustomLayoutOption customLayoutOption;
Widget _buildItem(BuildContext context, int index) {
return ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(_radius)),
child: Image.network(
images[index % images.length],
fit: BoxFit.fill,
),
);
}
@override
void didUpdateWidget(ExampleCustom oldWidget) {
customLayoutOption = CustomLayoutOption(startIndex: -1, stateCount: 3)
.addRotate([-45.0 / 180, 0.0, 45.0 / 180]).addTranslate(
[Offset(-370.0, -40.0), Offset(0.0, 0.0), Offset(370.0, -40.0)]);
super.didUpdateWidget(oldWidget);
}
@override
void initState() {
customLayoutOption = CustomLayoutOption(startIndex: -1, stateCount: 3)
.addRotate([-25.0 / 180, 0.0, 25.0 / 180]).addTranslate(
[Offset(-350.0, 0.0), Offset(0.0, 0.0), Offset(350.0, 0.0)]);
_fade = 1.0;
_currentIndex = 0;
_curve = Curves.ease;
_scale = 0.8;
_controller = SwiperController();
_layout = SwiperLayout.TINDER;
_radius = 10.0;
_padding = 0.0;
_loop = true;
_itemCount = 3;
_autoplay = false;
_autoplayDely = 3000;
_viewportFraction = 0.8;
_outer = false;
_scrollDirection = Axis.horizontal;
_autoplayDisableOnInteraction = false;
super.initState();
}
// maintain the index
Widget buildSwiper() {
return Swiper(
onTap: (int index) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(" page"),
),
body: Container(),
);
}));
},
customLayoutOption: customLayoutOption,
fade: _fade,
index: _currentIndex,
onIndexChanged: (int index) {
setState(() {
_currentIndex = index;
print(_currentIndex);
});
},
curve: _curve,
scale: _scale,
itemWidth: 300.0,
controller: _controller,
layout: _layout,
outer: _outer,
itemHeight: 200.0,
viewportFraction: _viewportFraction,
autoplayDelay: _autoplayDely,
loop: _loop,
autoplay: _autoplay,
itemBuilder: _buildItem,
itemCount: _itemCount,
scrollDirection: _scrollDirection,
indicatorLayout: PageIndicatorLayout.COLOR,
autoplayDisableOnInteraction: _autoplayDisableOnInteraction,
pagination: SwiperPagination(
builder: const DotSwiperPaginationBuilder(
size: 20.0, activeSize: 20.0, space: 10.0)),
);
}
SwiperController _controller;
TextEditingController numberController = TextEditingController();
@override
Widget build(BuildContext context) {
return Column(children: <Widget>[
Container(
color: Colors.black87,
child: SizedBox(
height: 300.0, width: double.infinity, child: buildSwiper()),
),
Expanded(
child: ListView(
children: <Widget>[
Text("Index:$_currentIndex"),
Row(
children: <Widget>[
RaisedButton(
onPressed: () {
_controller.previous(animation: true);
},
child: Text("Prev"),
),
RaisedButton(
onPressed: () {
_controller.next(animation: true);
},
child: Text("Next"),
),
Expanded(
child: TextField(
controller: numberController,
)),
RaisedButton(
onPressed: () {
var text = numberController.text;
setState(() {
_currentIndex = int.parse(text);
});
},
child: Text("Update"),
),
],
),
FormWidget(
label: "layout",
child: FormSelect(
placeholder: "Select layout",
value: _layout,
values: [
SwiperLayout.DEFAULT,
SwiperLayout.STACK,
SwiperLayout.TINDER,
SwiperLayout.CUSTOM
],
valueChanged: (value) {
_layout = value;
setState(() {});
})),
FormWidget(
label: "scrollDirection",
child: Switch(
value: _scrollDirection == Axis.horizontal,
onChanged: (bool value) => setState(() => _scrollDirection =
value ? Axis.horizontal : Axis.vertical)),
),
FormWidget(
label: "autoplayDisableOnInteractio",
child: Switch(
value: _autoplayDisableOnInteraction,
onChanged: (bool value) =>
setState(() => _autoplayDisableOnInteraction = value)),
),
//Pannel Begin
FormWidget(
label: "loop",
child: Switch(
value: _loop,
onChanged: (bool value) => setState(() => _loop = value)),
),
FormWidget(
label: "outer",
child: Switch(
value: _outer,
onChanged: (bool value) => setState(() => _outer = value)),
),
//Pannel Begin
FormWidget(
label: "autoplay",
child: Switch(
value: _autoplay,
onChanged: (bool value) => setState(() => _autoplay = value)),
),
FormWidget(
label: "padding",
child: NumberPad(
number: _padding,
step: 5.0,
min: 0.0,
max: 30.0,
onChangeValue: (num value) {
_padding = value.toDouble();
setState(() {});
},
),
),
FormWidget(
label: "scale",
child: NumberPad(
number: _scale,
step: 0.1,
min: 0.0,
max: 1.0,
onChangeValue: (num value) {
_scale = value.toDouble();
setState(() {});
},
),
),
FormWidget(
label: "fade",
child: NumberPad(
number: _fade,
step: 0.1,
min: 0.0,
max: 1.0,
onChangeValue: (num value) {
_fade = value.toDouble();
setState(() {});
},
),
),
FormWidget(
label: "itemCount",
child: NumberPad(
number: _itemCount,
step: 1,
min: 0,
max: 100,
onChangeValue: (num value) {
_itemCount = value.toInt();
setState(() {});
},
),
),
FormWidget(
label: "radius",
child: NumberPad(
number: _radius,
step: 1.0,
min: 0.0,
max: 30.0,
onChangeValue: (num value) {
this._radius = value.toDouble();
setState(() {});
},
),
),
FormWidget(
label: "viewportFraction",
child: NumberPad(
number: _viewportFraction,
step: 0.1,
max: 1.0,
min: 0.5,
onChangeValue: (num value) {
_viewportFraction = value.toDouble();
setState(() {});
},
),
),
FormWidget(
label: "curve",
child: FormSelect(
placeholder: "Select curve",
value: _layout,
values: [
Curves.easeInOut,
Curves.ease,
Curves.bounceInOut,
Curves.bounceOut,
Curves.bounceIn,
Curves.fastOutSlowIn
],
valueChanged: (value) {
_curve = value;
setState(() {});
})),
],
))
]);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(child: ExampleCustom()),
],
),
),
);
}
}