Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Listview that contain fixed listview

Tags:

flutter

dart

I would like to basically make a Settings Screen. Actually my screen look like that with Settings section that are composed of one title and a non-scrollable list view. I would like to put these sections in a list view to make the screen scrollable and to make every settings section following the last one.

Here is my actual screen.

Actual screen

And here is my code.

Widget build(BuildContext context) {
return Container(
    child: Column(
  crossAxisAlignment: CrossAxisAlignment.start,
  mainAxisAlignment: MainAxisAlignment.start,
  mainAxisSize: MainAxisSize.min,
  children: <Widget>[
        Expanded(
            child: SettingSection('Communication', [
          SettingsPayload('Email', 'Switch', () => (print('Function :)'))),
          SettingsPayload('Notifications', 'Switch'),
        ])),
        Expanded(
            child: SettingSection('Hello', [
          SettingsPayload('Email', 'Normal', () => print('value'),
              Icons.arrow_forward_ios),
          SettingsPayload('Notifications', 'Normal', () => print('hello')),
        ]))
  ],
));

How I build each list

buildlistSettings() {
return ListView.builder(
    physics: ScrollPhysics(parent: NeverScrollableScrollPhysics()),
    padding: const EdgeInsets.all(15.0),
    itemBuilder: (context, i) {
      if (i < widget.listSettings.length) {
        return Column(
          children: <Widget>[
            buildTileSettings(widget.listSettings[i]),
            Divider(),
          ],
        );
      }
    });
  }

@override


Widget build(BuildContext context) {
    return Container(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Container(
            padding: EdgeInsets.only(left : 10.0),
              height: 25.0,
              decoration:
                  BoxDecoration(color: Color.fromRGBO(223, 230, 233, 0.5), border: Border(bottom: BorderSide(color: Color.fromRGBO(223, 230, 233, 0.5), width: 1.0))),
              child: Row(children: <Widget>[Text(
                widget.title,
                style: TextStyle(fontSize: 15.0, color: Colors.blueGrey), 
              )])),
          Expanded(child: buildlistSettings()),
        ],
      ),
    );
  }
}
like image 607
Q. Eude Avatar asked Nov 22 '25 21:11

Q. Eude


1 Answers

I think there's a set of problems here not least of which is trying to put a ListView inside a ListView (and having to turn off scrolling), but mostly the use of Expanded which tries to fill up all the space in the relevant direction, but inside another container, which is itself unbounded.

I would use a ListView at the root, then build up the children using simple Column, ListTile and Divider widgets. Here's a working example (duplicated your data to ensure there's enough to scroll):

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

  MyHomePage({Key key, this.title}) : super(key: key);

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: ListView(
        children: <Widget>[
          SettingSection('Communication', [
            SettingsPayload('Email', 'Switch', () => (print('Function :)'))),
            SettingsPayload('Notifications', 'Switch'),
          ]),
          SettingSection('Hello', [
            SettingsPayload('Email', 'Normal', () => print('value'),
                Icons.arrow_forward_ios),
            SettingsPayload('Notifications', 'Normal', () => print('hello')),
          ]),
          SettingSection('Communication', [
            SettingsPayload('Email', 'Switch', () => (print('Function :)'))),
            SettingsPayload('Notifications', 'Switch'),
          ]),
          SettingSection('Hello', [
            SettingsPayload('Email', 'Normal', () => print('value'),
                Icons.arrow_forward_ios),
            SettingsPayload('Notifications', 'Normal', () => print('hello')),
          ]),
        ],
      ),
    );
  }
}

class SettingSection extends StatelessWidget {
  final String title;
  final List<SettingsPayload> payload;

  SettingSection(this.title, this.payload);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Container(
              padding: EdgeInsets.only(left: 10.0),
              height: 25.0,
              decoration: BoxDecoration(
                  color: Color.fromRGBO(223, 230, 233, 0.5),
                  border: Border(
                      bottom: BorderSide(
                          color: Color.fromRGBO(223, 230, 233, 0.5),
                          width: 1.0))),
              child: Row(children: <Widget>[
                Text(
                  this.title,
                  style: TextStyle(fontSize: 15.0, color: Colors.blueGrey),
                )
              ])),
          _buildListSettings(context),
        ],
      ),
    );
  }

  Widget _buildListSettings(BuildContext context) {
    List<Widget> items = List<Widget>();
    for (var setting in this.payload) {
      // TODO: Add logic here to determine what kind of setting widget to
      // create based on the payload.
      items.add(ListTile(
        title: Text(setting.title),
        trailing: Icon(setting.icon),
      ));
      items.add(Divider());
    }
    return Column(children: items);
  }
}

class SettingsPayload {
  final String title;
  final String type;
  final Function handler;
  final IconData icon;

  SettingsPayload(this.title, this.type, [this.handler, this.icon]);
}

You could use ListView.builder at the root level if your incoming settings data is variable and create SettingSection widgets for each item. Depends how you're handling your data.

like image 84
Derek Lakin Avatar answered Nov 25 '25 11:11

Derek Lakin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!