在 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.

处理您的“固定”视图,在本例中为:

  1. 顶部进度条...如果需要,您可以创建自定义进度条。
  2. 那个图片和用户名...

我们称他们为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();
  }
}