簡體   English   中英

如何在 ListView 中的 flutter 中創建一行可滾動的文本框或小部件?

[英]how to create a row of scrollable text boxes or widgets in flutter inside a ListView?

1.有人能告訴我如何在 ListView 中的 flutter 中創建一行可向左或向右滾動的文本框嗎? 我可以看到我正在嘗試在有限寬度的 ListView 中定義無限寬度。 但是,無法找出任何解決方法。

如果簡單地在 customscrollview 中注釋 scrolldirection 屬性(即,將 scrolldirection 更改為垂直),則下面提到的代碼絕對可以正常工作。 但是,我正在尋找水平滾動。 我試圖解決這個問題,但沒有運氣。

有人可以幫忙,讓我知道我哪里做錯了。

  1. 另外,我們如何像在 flutter 中的 Android 中那樣創建或擴充布局? 我已經包含了我正在創建的布局的屏幕截圖以供參考:

1[在此處輸入圖片描述

我已經發布了下面的代碼以重現相同的錯誤;

問候, 馬希

  import 'package:flutter/material.dart';
  import 'package:flutter/rendering.dart';
   import 'package:flutter/widgets.dart';
       void main(){
       runApp(new AddNewBlock());
       }

 class AddNewBlock extends StatefulWidget{

@override
State<StatefulWidget> createState() {
return new _AddNewBlockState();
    }
  }

   class _AddNewBlockState extends State<AddNewBlock>{


    @override
   Widget build(BuildContext context) {
   return new MaterialApp(
            title: 'Add New Block',
  debugShowCheckedModeBanner: false,

  home: new Scaffold(

    body: new ListView(
      shrinkWrap: true,

      children: <Widget>[
        new Container(
          margin: const EdgeInsets.only(
            left: 16.0,top: 24.0, bottom: 8.0,
          ),
          child: new Text(
            'Add New Block',
          style: new TextStyle(
            fontSize: 18.0,
            fontWeight: FontWeight.bold,
            color: Colors.teal[300],
    ),
          ),
        ),
        new Container(
          margin: const EdgeInsets.only(left: 16.0, top: 16.0, bottom: 8.0),
          child: new Text ('Block Name'),
        ),

        new Container(
          margin: const EdgeInsets.fromLTRB(16.0, 8.0, 0.0, 8.0),
          child: new Text ('Block A1',
          style: new TextStyle(
            fontSize: 16.0,
            fontWeight: FontWeight.bold
          ),),
        ),
        new Divider(color: Colors.grey,),
        new Container(
          margin: const EdgeInsets.only(left: 16.0, top: 8.0,bottom: 8.0),
          child: new Text('NO. OF FLOORS',
          style: new TextStyle(
            fontSize: 12.0,
          ),
          ),
        ),



       new Container(
                    child: new Row(
                      children: <Widget>[
                        new Flexible(
                          child: new CustomScrollView(
                            shrinkWrap: true,
                            scrollDirection: Axis.horizontal,
                            slivers: <Widget>[
                          new SliverPadding(
                          padding: const EdgeInsets.all(20.0),
                          sliver: new SliverList(
                            delegate: new SliverChildListDelegate(
                              <Widget>[
                                const Text('this'),
                                const Text('is'),
                                const Text('scroll'),
                                const Text('view'),
                                const Text('inside'),
                                const Text('list'),
                                const Text('view'),
                                const Text('in'),
                                const Text('horizontal'),
                                const Text('direction')
                              ],
                            ),
                          ),
                        ),
                      ],
                          ),
                        ),
                      ],
                    ),
                  ),





      ],

    ),
  ),


  );
   }
}

我認為這很簡單,只要您在水平ListView上放置一個固定高度的容器。 但也許我不明白你的問題。 如果這不起作用,請發布您的代碼和您收到的錯誤消息。

截屏

import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
import 'dart:collection';

void main() {
  runApp(new MaterialApp(home: new DemoApp()));
}

class DemoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: new Text('Nested ListView Example')),
      body: new Center(
        child: new ListView(
          children: <Widget>[
            new Container(
              height: 80.0,
              child: new ListView(
                scrollDirection: Axis.horizontal,
                children: new List.generate(10, (int index) {
                  return new Card(
                    color: Colors.blue[index * 100],
                    child: new Container(
                      width: 50.0,
                      height: 50.0,
                      child: new Text("$index"),
                    ),
                  );
                }),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

我這樣做是為了使我的 Row 小部件可滾動:

Text("Debilidades",
    style: TextStyle(fontWeight: FontWeight.bold)),
SingleChildScrollView(
  scrollDirection: Axis.horizontal,
  padding: EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
  child: Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: pokemon.weaknesses == null
          ? <Widget>[
              Text(
                "No tiene debilidades",
                style: TextStyle(color: Colors.grey),
              )
            ]
          : pokemon.weaknesses
              .map((weakness) => FilterChip(
                  backgroundColor: Colors.red,
                  label: Text(
                    weakness,
                    style: TextStyle(color: Colors.white),
                  ),

                  onSelected: (b) {}))
              .toList()),
),

在此處輸入圖片說明

對於要滾動的行/列,您只需使用SingleChildScrollView功能並根據需要提及方向。

SingleChildScrollView(
    scrollDirection: Axis.horizontal,
    child: Row(
        children: [
            //provide all the things u want to horizontally scroll here
        ]
    ),
);

您可以使用:

@override
Widget build(BuildContext context) {
  return Column(
    children: <Widget>[
      SizedBox( // Horizontal ListView
        height: 100,
        child: ListView.builder(
          itemCount: 20,
          scrollDirection: Axis.horizontal,
          itemBuilder: (context, index) {
            return Container(
              width: 100,
              alignment: Alignment.center,
              color: Colors.blue[(index % 9) * 100],
              child: Text(index.toString()),
            );
          },
        ),
      ),
      SizedBox( // Vertical ListView
        height: 200,
        child: ListView.builder(
          itemCount: 20,
          itemBuilder: (context, index) {
            return Container(
              width: 50,
              height: 50,
              alignment: Alignment.center,
              color: Colors.orange[(index % 9) * 100],
              child: Text(index.toString()),
            );
          },
        ),
      ),
    ],
  );
}

注意:為簡單起見,我沒有在單個 Widget 中重構兩個ListView

輸出

在此處輸入圖片說明

我通過使用ListView.builder()設法做到了這一點

這是完整的代碼:

import 'package:flutter/material.dart';


void main() {
  runApp(new MaterialApp(
      home: new MyApp()));
}

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new _MyAppState();
  }
}

class _MyAppState extends State<MyApp> {

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text("Scroll on the Horizon"),
          centerTitle: true,
        ),
        body: new ListView.builder(
          scrollDirection: Axis.horizontal,
          itemBuilder: (BuildContext context, int index) {
            return new Row(
              children: <Widget>[
                new Text("Let ", style: new TextStyle(color: Colors.blue),),
                new Text("me ", style: new TextStyle(color: Colors.red)),
                new Text("scroll ", style: new TextStyle(color: Colors.green)),
                new Text("horizontally ",
                    style: new TextStyle(color: Colors.orange)),
                new Text("Let ", style: new TextStyle(color: Colors.blue),),
                new Text("me ", style: new TextStyle(color: Colors.red)),
                new Text("scroll ", style: new TextStyle(color: Colors.green)),
                new Text("horizontally ",
                    style: new TextStyle(color: Colors.orange)),
                new Text("Let ", style: new TextStyle(color: Colors.blue),),
                new Text("me ", style: new TextStyle(color: Colors.red)),
                new Text("scroll ", style: new TextStyle(color: Colors.green)),
                new Text("horizontally ",
                    style: new TextStyle(color: Colors.orange)),
                new Text("Let ", style: new TextStyle(color: Colors.blue),),
                new Text("me ", style: new TextStyle(color: Colors.red)),
                new Text("scroll ", style: new TextStyle(color: Colors.green)),
                new Text("horizontally ",
                    style: new TextStyle(color: Colors.orange)),

              ],

            );
          },


        ));
  }

}

不要忘記將scrollDirection屬性設置為Axis.horizontal ,因為它默認為vertical值。

您可能想要創建嵌套 ListView

為了嘗試這個例子,你需要做的就是將下面的代碼復制粘貼到你新創建的 flutter 項目的 main.dart 文件中。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = "Nested ListView List";

    List<Choice> choices = const <Choice>[
      const Choice(
          title: 'MacBook Pro',
          date: '1 June 2019',
          description:
          'MacBook Pro (sometimes abbreviated as MBP) is a line of Macintosh portable computers introduced in January 2006 by Apple Inc.',
          imglink:
          'https://images.unsplash.com/photo-1517694712202-14dd9538aa97?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60'),
      const Choice(
          title: 'MacBook Air',
          date: '1 June 2016',
          description:
          'MacBook Air is a line of laptop computers developed and manufactured by Apple Inc. It consists of a full-size keyboard, a machined aluminum case, and a thin light structure.',
          imglink:
          'https://images.unsplash.com/photo-1499673610122-01c7122c5dcb?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60'),
      const Choice(
          title: 'iMac',
          date: '1 June 2019',
          description:
          'iMac is a family of all-in-one Macintosh desktop computers designed and built by Apple Inc. It has been the primary part of Apple consumer desktop offerings since its debut in August 1998, and has evolved through seven distinct forms.',
          imglink:
          'https://images.unsplash.com/photo-1517059224940-d4af9eec41b7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60'),
      const Choice(
          title: 'Mac Mini',
          date: '1 June 2017',
          description:
          'Mac mini (branded with lowercase "mini") is a desktop computer made by Apple Inc. One of four desktop computers in the current Macintosh lineup, along with the iMac, Mac Pro, and iMac Pro, it uses many components usually featured in laptops to achieve its small size.',
          imglink:
          'https://www.apple.com/v/mac-mini/f/images/shared/og_image__4mdtjbfhcduu_large.png?201904170831'),
      const Choice(
          title: 'Mac Pro',
          date: '1 June 2018',
          description:
          'Mac Pro is a series of workstation and server computer cases designed, manufactured and sold by Apple Inc. since 2006. The Mac Pro, in most configurations and in terms of speed and performance, is the most powerful computer that Apple offers.',
          imglink:
          'https://i0.wp.com/9to5mac.com/wp-content/uploads/sites/6/2017/01/mac-pro-2-concept-image.png?resize=1000%2C500&quality=82&strip=all&ssl=1'),
    ];

    return MaterialApp(
        title: title,
        home: Scaffold(
            appBar: AppBar(
              title: Text(title),
            ),
            body:
            ListView(
                children: [
                  Container(
                    height: 300.0,
                    child: ListView(
                        scrollDirection: Axis.horizontal,
                        shrinkWrap: true,
                        padding: const EdgeInsets.all(20.0),
                        children: List.generate(choices.length, (index) {
                          return Center(
                            child: ChoiceCard(
                                choice: choices[index], item: choices[index]),
                          );
                        })),
                  ),
                  Container(
                    height: 300.0,

                    child: ListView(
                        scrollDirection: Axis.horizontal,
                        shrinkWrap: true,
                        padding: const EdgeInsets.all(20.0),
                        children: List.generate(choices.length, (index) {
                          return Center(
                            child: ChoiceCard(
                                choice: choices[index], item: choices[index]),
                          );
                        })),
                  ),
                  Container(
                    height: 300.0,

                    child: ListView(
                        scrollDirection: Axis.horizontal,
                        shrinkWrap: true,
                        padding: const EdgeInsets.all(20.0),
                        children: List.generate(choices.length, (index) {
                          return Center(
                            child: ChoiceCard(
                                choice: choices[index], item: choices[index]),
                          );
                        })),
                  ),
                ])));
  }
}

class Choice {
  final String title;
  final String date;
  final String description;
  final String imglink;

  const Choice({this.title, this.date, this.description, this.imglink});
}

class ChoiceCard extends StatelessWidget {
  const ChoiceCard(
      {Key key,
        this.choice,
        this.onTap,
        @required this.item,
        this.selected: false})
      : super(key: key);

  final Choice choice;
  final VoidCallback onTap;
  final Choice item;
  final bool selected;

  @override
  Widget build(BuildContext context) {
    TextStyle textStyle = Theme.of(context).textTheme.display1;
    if (selected)
      textStyle = textStyle.copyWith(color: Colors.lightGreenAccent[400]);
    return Card(
        color: Colors.white,
        child: Column(
          children: <Widget>[
            new Expanded(
                child: Container(
                  width: 260.0,
                  height: 260.0,
                  child: Image.network(choice.imglink),
                )),
            new Container(
              width: 260.0,
              padding: const EdgeInsets.all(10.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Text(choice.title, style: Theme.of(context).textTheme.title),
                  Text(choice.date,
                      style: TextStyle(color: Colors.black.withOpacity(0.5))),
                  Text(choice.description),
                ],
              ),
            )
          ],
          crossAxisAlignment: CrossAxisAlignment.start,
        ));
  }
}

在此處輸入圖片說明

基於: 嵌套列表視圖

有多種方法可以在垂直 ListView 中顯示水平 ListView

  1. 使用帶有 SingleChildScrollView 的 Row 小部件
SingleChildScrollView(
  scrollDirection: Axis.horizontal,
  child: Row(
    children: List.generate(20, (x) => _listItem(x.toString()))
      .toList())),

或者,如果您有一個 List,那么您可以映射它並渲染它以代替 List.generate。 下面的示例假設 UserModel 具有屬性“firstName”。

e.g
List<UserModel> _list;
SingleChildScrollView(
   scrollDirection: Axis.horizontal,
   child: Row(
     children: _list.map((e) => _listItem(e.firstName)).toList())),
  1. 使用水平 ListView.builder
Container(
  height:50,// requires a finite vertical height  
  child: ListView.builder(
    itemCount: 50,
    scrollDirection: Axis.horizontal,
    itemBuilder: (_, index) => _listItem(index.toString())),
),
  1. 使用水平 ListView
ConstrainedBox(
  constraints: BoxConstraints(maxHeight: 50), // requires vertical bounded height
  child: ListView(
    scrollDirection: Axis.horizontal,
    children: List.generate(20, (x) => _listItem(x.toString()))
      .toList()),
),

我使用帶有水平滾動方向的 SingleChildScrollView 包裹的 Row 小部件實現了這一點,然后,我用另一行包裹了我的行小部件,以便添加一個大小的框小部件以在這些小部件之間形成間距。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM