在 flutter 中将故事项目更改为动态小部件
change story items as dynamic widgets in flutter
我想将故事项目实现为不同的小部件。就像这个例子:
这张图只改变了图片,但我想把整个widgets都改成story items。
我试过 story_view package。但是,在此包中,只能添加图像和视频。还有其他图书馆吗?
这可以通过 Stack, Container, and a GestureDetector 在 pages/stories 之间切换轻松实现。
为什么 Stacks?
Flutter's Stack
is useful if you want to overlap several
children in a simple way, for example, having some text and an image,
overlaid with a gradient and a button attached to the bottom.
处理您的“固定”视图,在本例中为:
- 顶部进度条...如果需要,您可以创建自定义进度条。
- 那个图片和用户名...
我们称他们为myTopFixedWidgets()
Row(children: [CircleAvatar(...),Column(children: [Text(...),Text(...)],)],)
现在,将您想要显示并发生变化的 Widget
(您的“故事”)作为 Stacks
的第一项,然后放置小部件 1. 和 2.(提到上面)在列表的第二项中。
维护一个变量index
以选择您要显示的小部件。
Stack(
children: <Widget>[
widgetsToShowAsAStory[index],
myTopFixedWidgets() //mentioned above
],
)
把它包在里面GestureDetector
List<Widget> widgetsToShowAsAStory = [];
var index = 0;
....
GestureDetector(
onTap: () {
//If the tap is on the LEFT side of the screen then decrement the value of the index
index-= 1; //(check for negatives)
//If the tap is on the RIGHT side of the screen then increment the value of the index
index+= 1; //(check for the size of list)
//call
setState() {}
},
child: Stack(
children: <Widget>[
widgetsToShowAsAStory[index],
myTopFixedWidgets()
],
),)
砰的一声,一切顺利!
我从 story_view 中找到了解决方案。但它不符合我的要求。我们只能显示不同的小部件,因为 story_view.We 中的故事项目无法对小部件执行任何操作。实现此 story_view 并将不同的小部件显示为故事。这样做吧。
首先从here.
导入story_view flutter dependencies
然后将其导入 main.dart 文件。
import "package:story_view/story_view.dart";
StoryView(
controller: controller,
storyItems: [
StoryItem.inlineImage(
url:
"https://images.unsplash.com/photo-1536063211352-0b94219f6212?ixid=MXwxMjA3fDB8MHxzZWFyY2h8MXx8YmVhdXRpZnVsJTIwZ2lybHxlbnwwfHwwfA%3D%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
controller: controller,
),
StoryItem(
new Container(
margin: EdgeInsets.all(12),
child: StaggeredGridView.countBuilder(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 12,
itemCount: imageList.length,
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(
Radius.circular(15))),
child: ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(15)),
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: imageList[index],
fit: BoxFit.cover,
),
),
);
},
staggeredTileBuilder: (index) {
return StaggeredTile.count(
1, index.isEven ? 1.2 : 1.8);
}),
),
duration: aLongWeekend,
shown: true),
StoryItem(
new Container(
margin: EdgeInsets.all(12),
child: StaggeredGridView.countBuilder(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 12,
itemCount: imageList.length,
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(
Radius.circular(15))),
child: ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(15)),
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: imageList[index],
fit: BoxFit.cover,
),
),
);
},
staggeredTileBuilder: (index) {
return StaggeredTile.count(
1, index.isEven ? 1.2 : 1.8);
}),
),
duration: aLongWeekend,
shown: true),
],
onStoryShow: (s) {
print("Showing a story");
},
onComplete: () {
print("Completed a cycle");
},
progressPosition: ProgressPosition.top,
repeat: false,
inline: false,
),
正如 https://whosebug.com/users/8164116/daksh-gargas 所解释的那样,可以使用堆栈页面视图和简单的手势检测器轻松实现故事视图。
做了一个简单的故事视图-
import 'package:flutter/material.dart';
class CustomStoryView extends StatefulWidget{
@override
_CustomStoryViewState createState() => _CustomStoryViewState();
}
class _CustomStoryViewState extends State<CustomStoryView> with SingleTickerProviderStateMixin {
final List _colorsList = [Colors.blue, Colors.red, Colors.green, Colors.yellow, Colors.grey, Colors.brown];
final PageController _controller = PageController();
double _progressIndicators;
int _page = 0;
AnimationController _animationController;
bool dragEnded = true;
Size _pageSize;
@override
void initState() {
_animationController = AnimationController(vsync: this, duration: Duration(seconds: 2));
_animationController.addListener(animationListener);
_animationController.forward();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
_pageSize = MediaQuery.of(context).size;
_progressIndicators = (_pageSize.width - 100) / 6;
});
super.initState();
}
@override
void dispose() {
_animationController?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
PageView.builder(
controller: _controller,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index)=>GestureDetector(
onLongPressStart: _onLongPressStart,
onLongPressEnd: _onLongPressEnd,
onHorizontalDragEnd: _onHorizontalDragEnd,
onHorizontalDragStart: _onHorizontalDragStart,
onHorizontalDragUpdate: _onHorizontalDragUpdate,
onTapUp: _onTapDown,
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
color: _colorsList[index],
child: Center(child: InkWell(
onTap: (){
print("thiswasclicked $index");
},
child: Text("Somee random text", style: TextStyle(fontSize: 36),)),),
),
),
itemCount: _colorsList.length,
),
Positioned(
top: 48,
left: 0,
right: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: ([0,1,2,3,4,5].map((e) =>
(e == _page) ? Stack(
children: [
Container(
width: _progressIndicators,
height: 8 ,
color: Colors.black54,
),
AnimatedBuilder(
animation: _animationController,
builder: (ctx, widget){
return AnimatedContainer(
width: _progressIndicators * _animationController.value,
height: 8 ,
color: Colors.white,
duration: Duration(milliseconds: 100),
);
},
),
],
): Container(
width: _progressIndicators,
height: 8 ,
color: (_page >= e) ? Colors.white : Colors.black54,
)).toList()),
),)
],
),
);
}
animationListener(){
if(_animationController.value == 1){
_moveForward();
}
}
_moveBackward(){
if(_controller.page != 0){
setState(() {
_page = (_controller.page - 1).toInt();
_page = (_page < 0) ? 0 : _page;
_controller.animateToPage(_page, duration: Duration(milliseconds: 100), curve: Curves.easeIn);
_animationController.reset();
_animationController.forward();
});
}
}
_moveForward(){
if(_controller.page != (_colorsList.length - 1)){
setState(() {
_page = (_controller.page + 1).toInt();
_controller.animateToPage(_page, duration: Duration(milliseconds: 100), curve: Curves.easeIn);
_animationController.reset();
_animationController.forward();
});
}
}
_onTapDown(TapUpDetails details) {
var x = details.globalPosition.dx;
(x < _pageSize.width / 2) ? _moveBackward() : _moveForward();
}
_onHorizontalDragUpdate(d){
if (!dragEnded) {
dragEnded = true;
if (d.delta.dx < -5) {
_moveForward();
} else if (d.delta.dx > 5) {
_moveBackward();
}
}
}
_onHorizontalDragStart(d) {
dragEnded = false;
}
_onHorizontalDragEnd(d) {
dragEnded = true;
}
_onLongPressEnd(_){
_animationController.forward();
}
_onLongPressStart(_){
_animationController.stop();
}
}
我想将故事项目实现为不同的小部件。就像这个例子:
这张图只改变了图片,但我想把整个widgets都改成story items。
我试过 story_view package。但是,在此包中,只能添加图像和视频。还有其他图书馆吗?
这可以通过 Stack, Container, and a GestureDetector 在 pages/stories 之间切换轻松实现。
为什么 Stacks?
Flutter's
Stack
is useful if you want to overlap several children in a simple way, for example, having some text and an image, overlaid with a gradient and a button attached to the bottom.
处理您的“固定”视图,在本例中为:
- 顶部进度条...如果需要,您可以创建自定义进度条。
- 那个图片和用户名...
我们称他们为myTopFixedWidgets()
Row(children: [CircleAvatar(...),Column(children: [Text(...),Text(...)],)],)
现在,将您想要显示并发生变化的 Widget
(您的“故事”)作为 Stacks
的第一项,然后放置小部件 1. 和 2.(提到上面)在列表的第二项中。
维护一个变量index
以选择您要显示的小部件。
Stack(
children: <Widget>[
widgetsToShowAsAStory[index],
myTopFixedWidgets() //mentioned above
],
)
把它包在里面GestureDetector
List<Widget> widgetsToShowAsAStory = [];
var index = 0;
....
GestureDetector(
onTap: () {
//If the tap is on the LEFT side of the screen then decrement the value of the index
index-= 1; //(check for negatives)
//If the tap is on the RIGHT side of the screen then increment the value of the index
index+= 1; //(check for the size of list)
//call
setState() {}
},
child: Stack(
children: <Widget>[
widgetsToShowAsAStory[index],
myTopFixedWidgets()
],
),)
砰的一声,一切顺利!
我从 story_view 中找到了解决方案。但它不符合我的要求。我们只能显示不同的小部件,因为 story_view.We 中的故事项目无法对小部件执行任何操作。实现此 story_view 并将不同的小部件显示为故事。这样做吧。
首先从here.
导入story_view flutter dependencies然后将其导入 main.dart 文件。
import "package:story_view/story_view.dart";
StoryView(
controller: controller,
storyItems: [
StoryItem.inlineImage(
url:
"https://images.unsplash.com/photo-1536063211352-0b94219f6212?ixid=MXwxMjA3fDB8MHxzZWFyY2h8MXx8YmVhdXRpZnVsJTIwZ2lybHxlbnwwfHwwfA%3D%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
controller: controller,
),
StoryItem(
new Container(
margin: EdgeInsets.all(12),
child: StaggeredGridView.countBuilder(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 12,
itemCount: imageList.length,
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(
Radius.circular(15))),
child: ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(15)),
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: imageList[index],
fit: BoxFit.cover,
),
),
);
},
staggeredTileBuilder: (index) {
return StaggeredTile.count(
1, index.isEven ? 1.2 : 1.8);
}),
),
duration: aLongWeekend,
shown: true),
StoryItem(
new Container(
margin: EdgeInsets.all(12),
child: StaggeredGridView.countBuilder(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 12,
itemCount: imageList.length,
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(
Radius.circular(15))),
child: ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(15)),
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: imageList[index],
fit: BoxFit.cover,
),
),
);
},
staggeredTileBuilder: (index) {
return StaggeredTile.count(
1, index.isEven ? 1.2 : 1.8);
}),
),
duration: aLongWeekend,
shown: true),
],
onStoryShow: (s) {
print("Showing a story");
},
onComplete: () {
print("Completed a cycle");
},
progressPosition: ProgressPosition.top,
repeat: false,
inline: false,
),
正如 https://whosebug.com/users/8164116/daksh-gargas 所解释的那样,可以使用堆栈页面视图和简单的手势检测器轻松实现故事视图。
做了一个简单的故事视图-
import 'package:flutter/material.dart';
class CustomStoryView extends StatefulWidget{
@override
_CustomStoryViewState createState() => _CustomStoryViewState();
}
class _CustomStoryViewState extends State<CustomStoryView> with SingleTickerProviderStateMixin {
final List _colorsList = [Colors.blue, Colors.red, Colors.green, Colors.yellow, Colors.grey, Colors.brown];
final PageController _controller = PageController();
double _progressIndicators;
int _page = 0;
AnimationController _animationController;
bool dragEnded = true;
Size _pageSize;
@override
void initState() {
_animationController = AnimationController(vsync: this, duration: Duration(seconds: 2));
_animationController.addListener(animationListener);
_animationController.forward();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
_pageSize = MediaQuery.of(context).size;
_progressIndicators = (_pageSize.width - 100) / 6;
});
super.initState();
}
@override
void dispose() {
_animationController?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
PageView.builder(
controller: _controller,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index)=>GestureDetector(
onLongPressStart: _onLongPressStart,
onLongPressEnd: _onLongPressEnd,
onHorizontalDragEnd: _onHorizontalDragEnd,
onHorizontalDragStart: _onHorizontalDragStart,
onHorizontalDragUpdate: _onHorizontalDragUpdate,
onTapUp: _onTapDown,
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
color: _colorsList[index],
child: Center(child: InkWell(
onTap: (){
print("thiswasclicked $index");
},
child: Text("Somee random text", style: TextStyle(fontSize: 36),)),),
),
),
itemCount: _colorsList.length,
),
Positioned(
top: 48,
left: 0,
right: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: ([0,1,2,3,4,5].map((e) =>
(e == _page) ? Stack(
children: [
Container(
width: _progressIndicators,
height: 8 ,
color: Colors.black54,
),
AnimatedBuilder(
animation: _animationController,
builder: (ctx, widget){
return AnimatedContainer(
width: _progressIndicators * _animationController.value,
height: 8 ,
color: Colors.white,
duration: Duration(milliseconds: 100),
);
},
),
],
): Container(
width: _progressIndicators,
height: 8 ,
color: (_page >= e) ? Colors.white : Colors.black54,
)).toList()),
),)
],
),
);
}
animationListener(){
if(_animationController.value == 1){
_moveForward();
}
}
_moveBackward(){
if(_controller.page != 0){
setState(() {
_page = (_controller.page - 1).toInt();
_page = (_page < 0) ? 0 : _page;
_controller.animateToPage(_page, duration: Duration(milliseconds: 100), curve: Curves.easeIn);
_animationController.reset();
_animationController.forward();
});
}
}
_moveForward(){
if(_controller.page != (_colorsList.length - 1)){
setState(() {
_page = (_controller.page + 1).toInt();
_controller.animateToPage(_page, duration: Duration(milliseconds: 100), curve: Curves.easeIn);
_animationController.reset();
_animationController.forward();
});
}
}
_onTapDown(TapUpDetails details) {
var x = details.globalPosition.dx;
(x < _pageSize.width / 2) ? _moveBackward() : _moveForward();
}
_onHorizontalDragUpdate(d){
if (!dragEnded) {
dragEnded = true;
if (d.delta.dx < -5) {
_moveForward();
} else if (d.delta.dx > 5) {
_moveBackward();
}
}
}
_onHorizontalDragStart(d) {
dragEnded = false;
}
_onHorizontalDragEnd(d) {
dragEnded = true;
}
_onLongPressEnd(_){
_animationController.forward();
}
_onLongPressStart(_){
_animationController.stop();
}
}