颤动水平列表视图/页面视图,选定元素动画到全宽

Posted

技术标签:

【中文标题】颤动水平列表视图/页面视图,选定元素动画到全宽【英文标题】:Flutter horizontal Listview/Pageview with selected element animated to full width 【发布时间】:2021-02-01 05:47:12 【问题描述】:

所以基本上我只想有一个水平对齐ListViewPageView 里面的项目,当前选择的项目将占据整个可用的全宽。到目前为止,这是我的基本代码:

    import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget 
  @override
  _MyAppState createState() => _MyAppState();


// Initialize DATA MODEL list with some random values.
List<DataModel> dataList = ['Andrew', 'Test', 'Data', 'Random']
    .map<DataModel>((s) => DataModel(s))
    .toList();

double containerWidth;

class _MyAppState extends State<MyApp> 
  @override
  Widget build(BuildContext context) 
    //var fWidth = MediaQuery.of(context).size.height * 1;

    return MaterialApp(
        title: 'Adjustable height card.',
        home: Scaffold(
          body: ListView.builder(
            controller: PageController(viewportFraction: 0.8),
            scrollDirection: Axis.horizontal,
            itemCount: dataList.length,
            itemBuilder: (context, index) 
              DataModel item = dataList.elementAt(index);

              // Check if the item is expanded or not and set size accordingly
              containerWidth = item.expanded
                  ? MediaQuery.of(context).size.width * 1
                  : MediaQuery.of(context).size.width * 0.30;

              return GestureDetector(
                onDoubleTap: () 
                  setState(() 
                    item.expanded = !item.expanded;
                  );
                ,
                child: AnimatedContainer(
                  curve: Curves.easeOut,
                  duration: Duration(milliseconds: 400),
                  color: Colors.red,
                  width: containerWidth,
                  margin: EdgeInsets.all(8),
                  child: Center(
                    child: Text(
                      dataList.elementAt(index).title,
                      style: TextStyle(
                        color: Colors.white,
                      ),
                    ),
                  ),
                ),
              );
            ,
          ),
        ));
  


class DataModel 
  String title;
  bool expanded;

  DataModel(this.title) 
    expanded = false;
  

正如您现在所看到的,我可以为所选元素提供全宽,但我需要进行某种页面捕捉,因为目前我无法很好地跳过大容器或小容器。现在,如果我将整个内容更改为PageView,我将无法再控制AnimatedContainer 的宽度。请帮忙。

【问题讨论】:

【参考方案1】:

您应该可以控制宽度,为什么不呢?您是否尝试过使用 PageView.builder 方法?

【讨论】:

我的目标是让我们说 5 个宽度为 200 的项目,您应该已经在视图中看到 2 个项目。现在如果我们在选定的项目上,它应该变成 100% 设备宽度。 点击后,您可以为每个小部件指定媒体查询大小。 在 pageviewbuilder 中,所有项目始终全屏显示。你能给我一个可用的例子吗? 只需将内容包装到一个 Container 小部件中(如果需要,可以将小部件居中)。【参考方案2】:
    import 'package:flutter/material.dart';

void main() 
  runApp(MaterialApp(
    home: MyApp(),
  ));

class MyApp extends StatefulWidget 
  @override
  _MyAppState createState() => _MyAppState();


// Initialize DATA MODEL list with some random values.
List<DataModel> dataList = ['Andrew', 'Test', 'Data', 'Random']
    .map<DataModel>((s) => DataModel(s))
    .toList();

double containerWidth;

class _MyAppState extends State<MyApp> 
  @override
  Widget build(BuildContext context) 

    return MaterialApp(
        title: 'Adjustable height card.',
        home: Scaffold(
          body: ListView(children: getViewList(),controller: PageController(viewportFraction: 0.8),
            scrollDirection: Axis.horizontal,)
        ));
  
  List<Widget> getViewList()
  
    var listOfWidgets = List<Widget>();


    for (var item in dataList) 
      containerWidth = item.expanded
          ? MediaQuery.of(context).size.width* 1
          :  MediaQuery.of(context).size.width * 0.30;
      listOfWidgets.add(GestureDetector(
        onDoubleTap: () 
          print("onDoubleTap");
          setState(() 
            for (var item in dataList)
              item.expanded=false;
            item.expanded = !item.expanded;
          );
        ,
        child: AnimatedContainer(
          curve: Curves.easeOut,
          duration: Duration(milliseconds: 100),
          color: Colors.red,
          width: containerWidth,
          margin: EdgeInsets.all(8),
          child: Center(
            child: Text(
              item.title,
              style: TextStyle(
                color: Colors.white,
              ),
            ),
          ),
        ),
      )); // TODO: Whatever layout you need for each widget.
    

    return listOfWidgets;
  



class DataModel 
  String title;
  bool expanded;

  DataModel(this.title) 
    expanded = false;
  

【讨论】:

以上是关于颤动水平列表视图/页面视图,选定元素动画到全宽的主要内容,如果未能解决你的问题,请参考以下文章

在水平堆栈视图 + 元素的全宽上注册 UITapGesture

在垂直列表视图中颤动动态高度水平列表视图

如何在颤动中制作水平滚动动画

自定义滚动谷歌颤动中的水平列表视图

视频视图中的 Android 全宽

页面视图滚动上的颤动文本动画