简体   繁体   English

如何在颤振中创建完全可水平滚动的垂直列表

[英]How to create a vertical list fully horizontally scrollable in flutter

I have a need for vertical list who's elements exceed the width of the display (similar to a wide Flutter Datatable).我需要垂直列表谁的元素超过显示的宽度(类似于宽的 Flutter 数据表)。 So I'd like to make the vertically scrollable list also scrollable horizontally.所以我想让垂直滚动列表也可以水平滚动。 It seems the way to do this would be to put the list in a SingleChildScrollView似乎这样做的方法是将列表放在 SingleChildScrollView 中

   SingleChildScrollView(child: listview, scrollDirection: Axis.horizontal);

... which works, but apparently not if the listview contains a row as an element: ...这是有效的,但如果列表视图包含一行作为元素,则显然无效:

 Row(
    mainAxisAlignment: MainAxisAlignment.start,
    crossAxisAlignment: CrossAxisAlignment.start,
    mainAxisSize: MainAxisSize.min,
    children: children.toList());

I don't understand why this is a problem, since this kind of row should have a finite width (due to MainAxisSize.min).我不明白为什么这是一个问题,因为这种行应该有一个有限的宽度(由于 MainAxisSize.min)。

It's possible to wrap each list element in a SingleChildScrollView, but this leads only to the single element being scrollable.可以将每个列表元素包装在 SingleChildScrollView 中,但这只会导致单个元素可滚动。

I can't use Datatable in a SingleChildScrollView for this because it doesn't support variably sized cell heights.为此,我不能在 SingleChildScrollView 中使用 Datatable,因为它不支持可变大小的单元格高度。 how to create horizontally scrollable vertical listview in Flutter? 如何在 Flutter 中创建可水平滚动的垂直列表视图?


Widget test() {
  Widget child = ListView.builder(
      itemCount: 2,
      shrinkWrap: true,
      itemBuilder: (context, i) {
        Widget child = rowSSMin_([
          Text(
              "AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA"),
          Text(
              "BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB"),
          Text(
              "XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX"),
        ]);
        return child;
      });

  child = scrollH(child);  // < breaks

  return child;
}

//////////////////////////////////////////////////////////////////////////////
//

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            body: Center(
                child: Padding(padding: EdgeInsets.all(20), child: test()))));
  }
}


Widget scrollH(Widget child, {ScrollController controller}) =>
    SingleChildScrollView(child: child, scrollDirection: Axis.horizontal, controller: controller);

Widget columnSSMin_(List<Widget> children) => Column(
    mainAxisAlignment: MainAxisAlignment.start,
    crossAxisAlignment: CrossAxisAlignment.start,
    mainAxisSize: MainAxisSize.min,
    children: children);

Widget rowSSMin_(Iterable<Widget> children) => Row(
    mainAxisAlignment: MainAxisAlignment.start,
    crossAxisAlignment: CrossAxisAlignment.start,
    mainAxisSize: MainAxisSize.min,
    children: children.toList());

gets...得到...

════════ Exception caught by rendering library ═════════════════════════════════════════════════════
The following assertion was thrown during performLayout():
RenderBox was not laid out: RenderSemanticsAnnotations#fe879 relayoutBoundary=up10 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1785 pos 12: 'hasSize'


Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
  https://github.com/flutter/flutter/issues/new?template=BUG.md

The relevant error-causing widget was: 
  SingleChildScrollView file:///home/sir/ailive/livebetter/flutterui/lib/scratch2.dart:41:31
When the exception was thrown, this was the stack: 
#2      RenderBox.size (package:flutter/src/rendering/box.dart:1785:12)
#3      RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:114:21)
#4      RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
#5      RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
#6      RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
...
The following RenderObject was being processed when the exception was fired: RenderPointerListener#ea643 relayoutBoundary=up9 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...  parentData: <none> (can use size)
...  constraints: BoxConstraints(0.0<=w<=921.5, 0.0<=h<=512.9)
...  size: MISSING
...  behavior: opaque
...  listeners: down
RenderObject: RenderPointerListener#ea643 relayoutBoundary=up9 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
  parentData: <none> (can use size)
  constraints: BoxConstraints(0.0<=w<=921.5, 0.0<=h<=512.9)
  size: MISSING
  behavior: opaque
  listeners: down
...  child: RenderSemanticsAnnotations#fe879 relayoutBoundary=up10 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...    parentData: <none> (can use size)
...    constraints: BoxConstraints(0.0<=w<=921.5, 0.0<=h<=512.9)
...    size: MISSING
...    child: RenderIgnorePointer#74492 relayoutBoundary=up11 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(0.0<=w<=921.5, 0.0<=h<=512.9)
...      size: MISSING
...      ignoring: false
...      ignoringSemantics: false
...      child: _RenderSingleChildViewport#3aec9 relayoutBoundary=up12 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...        needs compositing
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(0.0<=w<=921.5, 0.0<=h<=512.9)
...        size: MISSING
...        child: RenderRepaintBoundary#4986d relayoutBoundary=up13 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...          needs compositing
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(0.0<=w<=Infinity, 0.0<=h<=512.9)
...          size: MISSING
...          usefulness ratio: no metrics collected yet (never painted)

Tying each row to a ScrollController also doesn't seem to get the whole list to scroll horizontally in unison:将每一行绑定到 ScrollController 似乎也不会让整个列表一致地水平滚动:

Widget test() {
  ScrollController controller = ScrollController();

  Widget child = ListView.builder(
      itemCount: 2,
      shrinkWrap: true,
      itemBuilder: (context, i) {
        Widget child = rowSSMin_([
          Text(
              "AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA"),
          Text(
              "BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB"),
          Text(
              "XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX"),
        ]);
        child = scrollH(child, controller:controller);  // Added
        return child;
      });

  // child = scrollH(child, controller:controller);  // Removed

  return child;
}

You can try wrapping your scrollable widgets with a Container and setting its height and width to the device's size:您可以尝试使用 Container 包装可滚动小部件并将其高度和宽度设置为设备的大小:

Container(
  height: MediaQuery.of(context).size.height,
  width: MediaQuery.of(context).size.width,
  child: yourVerticallyOrHorizontallyScrollableWidget
)

Yes you can, but with 2 SingleChildScrollView and make sure that it has no ListView in it.是的,您可以,但是使用 2 SingleChildScrollView 并确保其中没有 ListView。

     SingleChildScrollView(
        scrollDirection: Axis.vertical,
        child: SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          child: Column(
            children: [ 
            \\ Your widgets
            ],
          ),
        ),
      ),

update更新

If you want to use ListView.builder as you said at the comments, You should do 2 things:如果你想像评论中所说的那样使用 ListView.builder ,你应该做两件事:

1- add this attribute for the listView : 1- 为 listView 添加此属性:

physics: NeverScrollableScrollPhysics()

2- add the listview inside any widget that should have width and height. 2- 在任何应该具有宽度和高度的小部件中添加列表视图。 and this width should be more than the width of the screen.并且这个宽度应该大于屏幕的宽度。

This is the code这是代码

@override
  Widget build(BuildContext context) {
    return SafeArea(
      child: new Scaffold(
        body: SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          child: SingleChildScrollView(
            scrollDirection: Axis.vertical,
            child: Container(
              width: MediaQuery.of(context).size.width * 1.8,
              height: MediaQuery.of(context).size.height,
              child: ListView.builder(
                  physics: NeverScrollableScrollPhysics(),
                  scrollDirection: Axis.vertical,
                  itemCount: 24,
                  shrinkWrap: false,
                  itemBuilder: (context, i) {
                    return Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                                "AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA"),
                            Text(
                                "BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB BBB"),
                            Text(
                                "XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX"),
                          ]),
                    );
                  }),
            ),
          ),
        ),
      ),
    );
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM