Flutter Scrolling widgets

默认情况下,布局组件内的子组件内容超出容器宽度时会出现一个溢出警告

import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Row'),
      ),
      body: Stack(
        children: [
          Row(
            children: List.generate(
              20,
              (index) => OutlinedButton(
                onPressed: () {},
                child: Text('按钮 ${index + 1}'),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

 

列表 -- SingleChildScrollView

支持单组件滚动,类似 Android 中的 ScrollView

属性:
child:Widget,单个子组件
padding:EdgeInsets,内边距
scrollDirection:Axis,滚动方向,默认值 vertical(Axis.horizontal | Axis.vertical)
reverse:bool,初始滚动位置,默认值 false(false:头部,true:尾部)
physics
  ClampingScrollPhysics:Android 下微光效果
  BouncingScrollPhysics:IOS 下弹性效果
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('SingleChildScrollView'),
      ),
      body: Stack(
        children: [
          // 水平方向的滚动
          Container(
            width: double.infinity,
            padding: const EdgeInsets.all(10),
            child: SingleChildScrollView(
              scrollDirection: Axis.horizontal,
              padding: const EdgeInsets.all(10),
              // 初始滚动位置:尾部
              reverse: true,
              // 触底效果
              physics: const ClampingScrollPhysics(),
              child: Row(
                children: List.generate(
                  20,
                  (index) => OutlinedButton(
                    onPressed: () {},
                    child: Text('按钮 ${index + 1}'),
                  ),
                ),
              ),
            ),
          ),
          // 垂直方向的滚动
          Container(
            width: double.infinity,
            margin: const EdgeInsets.only(top: 100),
            padding: const EdgeInsets.all(10),
            child: SingleChildScrollView(
              scrollDirection: Axis.vertical,
              padding: const EdgeInsets.all(10),
              // 初始滚动位置:头部
              reverse: false,
              // 触底效果
              physics: const BouncingScrollPhysics(),
              child: Column(
                children: List.generate(
                  20,
                  (index) => OutlinedButton(
                    onPressed: () {},
                    child: Text('按钮 ${index + 1}'),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

 

列表 -- ListView

ListView
加载列表的组件(加载所有 Widgets,适用 Widget 较少的场景)
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('ListView'),
      ),
      body: Column(
        children: [
          Container(
            height: 200,
            color: Colors.yellow[100],
            padding: const EdgeInsets.all(10),
            child: ListView(
              // 默认垂直方向滚动
              children: const [
                ListTile(
                  leading: Icon(
                    Icons.favorite,
                    size: 50,
                  ),
                  title: Text('收藏'),
                  subtitle: Text('子标题'),
                  trailing: Icon(Icons.keyboard_arrow_right),
                  // 是否选中,默认值 false
                  selected: true,
                  // 选中的文本和icon的颜色
                  selectedColor: Colors.red,
                ),
                ListTile(
                  leading: Icon(
                    Icons.audiotrack,
                    size: 50,
                  ),
                  title: Text('音乐'),
                  subtitle: Text('子标题'),
                  trailing: Icon(Icons.keyboard_arrow_right),
                ),
                ListTile(
                  leading: Icon(
                    Icons.beach_access,
                    size: 50,
                  ),
                  title: Text('海滩'),
                  subtitle: Text('子标题'),
                  trailing: Icon(Icons.keyboard_arrow_right),
                ),
                ListTile(
                  leading: Icon(
                    Icons.shopping_cart,
                    size: 50,
                  ),
                  title: Text('购物车'),
                  subtitle: Text('子标题'),
                  trailing: Icon(Icons.keyboard_arrow_right),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('ListView Horizontal'),
      ),
      body: Container(
        height: 100,
        padding: const EdgeInsets.all(10),
        child: ListView(
          // 水平方向滚动
          scrollDirection: Axis.horizontal,
          children: [
            Container(
              width: 100,
              color: Colors.yellow,
            ),
            Container(
              width: 100,
              color: Colors.blueGrey,
            ),
            Container(
              width: 100,
              color: Colors.pink[100],
            ),
            Container(
              width: 100,
              color: Colors.green[100],
            ),
            Container(
              width: 100,
              color: Colors.red[100],
            ),
            Container(
              width: 100,
              color: Colors.purple[300],
            ),
          ],
        ),
      ),
    );
  }
}

 

ListView.builder
按需加载 Widget,性能比默认构造函数高,适用 Widget 较多的场景
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  List<Widget> getUsers() {
    return List<Widget>.generate(
      20,
      (index) => OutlinedButton(
        onPressed: () {},
        child: Text('按钮 $index'),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> userList = getUsers();
    return Scaffold(
      appBar: AppBar(
        title: const Text('ListView.builder'),
      ),
      body: Container(
        height: 150,
        padding: const EdgeInsets.all(10),
        child: ListView.builder(
          // 列表数量
          itemCount: userList.length,
          // 列表子组件高度
          itemExtent: 50,
          // 列表子组件构造器
          itemBuilder: (context, index) {
            return userList[index];
          },
        ),
      ),
    );
  }
}

 

 
ListView.separated
比 ListView.builder 多了个分隔器
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  List<Widget> getProducts() {
    return List<Widget>.generate(
      20,
      (index) => ListTile(
        leading: Image.network(
          'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
        ),
        title: Text('商品标题 ${index + 1}'),
        subtitle: const Text('子标题'),
        trailing: const Icon(Icons.keyboard_arrow_right),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> products = getProducts();
    // 偶数分隔器
    Widget dividerOdd = const Divider(
      color: Colors.red,
      thickness: 2, // 分隔线的粗细
    );
    // 奇数分隔器
    Widget dividerEven = const Divider(
      color: Colors.green,
      thickness: 2,
    );
    return Scaffold(
      appBar: AppBar(
        title: const Text('ListView.seperated'),
      ),
      body: Column(
        children: [
          const ListTile(title: Text('商品列表')),
          Container(
            height: 200,
            padding: const EdgeInsets.symmetric(horizontal: 10),
            child: ListView.separated(
              // 列表的数量
              itemCount: products.length,
              // 列表子组件构造器
              itemBuilder: (context, index) {
                return products[index];
              },
              // 分隔器的构造器
              separatorBuilder: (context, index) {
                return index % 2 == 0 ? dividerEven : dividerOdd;
              },
            ),
          ),
        ],
      ),
    );
  }
}

 

列表 -- GridView(网格布局)

属性:
children:Widgets,子组件
scrollDirection:滚动方向
gridDelegate:
  SilverGridDelegateWithFixedCrossAxisCount:指定列数,子组件宽度自适应
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('GridView'),
      ),
      body: Container(
        width: double.infinity,
        padding: const EdgeInsets.all(10),
        child: GridView(
          gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 4, // 必填,指定列数
            mainAxisSpacing: 20, // 主轴方向的间距
            crossAxisSpacing: 20, // 交叉轴方向的间距
          ),
          children: [
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_1003.jpg',
            ),
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_1007.jpg',
            ),
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_1023.jpg',
            ),
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_10263.jpg',
            ),
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_10715.jpg',
            ),
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_10822.jpg',
            ),
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_10832.jpg',
            ),
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_10982.jpg',
            ),
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_11006.jpg',
            ),
          ],
        ),
      ),
    );
  }
}

 

  SilverGridDelegateWithMaxCrossAxisCount:指定子组件宽度,列数自适应
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('GridView'),
      ),
      body: Container(
        width: double.infinity,
        padding: const EdgeInsets.all(10),
        child: GridView(
          gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
            maxCrossAxisExtent: 120, // 必填,子组件的最大宽度
            mainAxisSpacing: 20,
            crossAxisSpacing: 20,
          ),
          children: [
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_1003.jpg',
            ),
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_1007.jpg',
            ),
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_1023.jpg',
            ),
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_10263.jpg',
            ),
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_10715.jpg',
            ),
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_10822.jpg',
            ),
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_10832.jpg',
            ),
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_10982.jpg',
            ),
            Image.network(
              'https://images.dog.ceo/breeds/hound-afghan/n02088094_11006.jpg',
            ),
          ],
        ),
      ),
    );
  }
}


GirdView.count() 列数固定
 
属性:
crossAxisCount:int,必填项,列数
scrollDirection:Axis,默认值 veritical,滚动方向,默认纵向滚动
mainAxisSpacing:double,主轴方向的子组件间距
crossAxisSpacing:double,交叉轴方向的子组件间距
childAspectRadio:double,子组件的分辨率,默认值 1.0
children:List<Widget>,子组件
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('GridView.count'),
      ),
      body: Container(
        padding: const EdgeInsets.all(10),
        child: GridView.count(
          // scrollDirection: Axis.horizontal,
          crossAxisCount: 2, // 列数
          mainAxisSpacing: 10, // 交叉轴上(水平)子组件之间的间距
          crossAxisSpacing: 20, // 主轴上(垂直)子组件之间的间距
          childAspectRatio: 2, // 子组件的缩放比例
          children: List.generate(
            10,
            (index) => Image.asset('assets/image2.jpg'),
          ),
        ),
      ),
    );
  }
}

 

GridView.extent() 子组件宽度固定

属性:
maxCrossAxisExtent:double,必填项,子组件最大宽度
scrollDirection:Axis,默认值 veritical,滚动方向,默认纵向滚动
mainAxisSpacing:double,主轴方向的子组件间距
crossAxisSpacing:double,交叉轴方向的子组件间距
childAspectRadio:double,子组件的分辨率,默认值 1.0
children:List<Widget>,子组件
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('GridView.extent'),
      ),
      body: Container(
        padding: const EdgeInsets.all(10),
        child: GridView.extent(
          maxCrossAxisExtent: 120, // 子组件最大宽度
          mainAxisSpacing: 10, // 主轴方向(纵向)子组件间距
          crossAxisSpacing: 10, // 交叉轴(横向)子组件间距
          // scrollDirection: Axis.horizontal,
          children: List.generate(
            50,
            (index) => Image.network(
                'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'),
          ),
        ),
      ),
    );
  }
}

 

 
GridView.builder() 动态网格布局

physics:ScrollPhysics,确定可滚动控件的物理特性

BouncingScrollPhysics():允许超出边界 -- 反弹效果
ClampingScrollPhysics():防止超出边界 -- 夹住效果
AlwaysScrollableScrollPhysics():始终响应滚动
NeverScrollableScrollPhysics():不响应滚动
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final List<Image> images = List<Image>.generate(
      50,
      (index) => Image.network(
        'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
      ),
    );
    return Scaffold(
      appBar: AppBar(
        title: const Text('GridView.builder'),
      ),
      body: Container(
        padding: const EdgeInsets.all(10),
        child: GridView.builder(
          gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 2,
            mainAxisSpacing: 10,
            crossAxisSpacing: 10,
          ),
          itemCount: images.length,
          itemBuilder: (context, index) {
            return images[index];
          },
          physics: const BouncingScrollPhysics(), // 反弹效果
          // physics: const ClampingScrollPhysics(), // 夹住的效果(触底没什么反应)
          // physics: const AlwaysScrollableScrollPhysics(), // 滚动
          // physics: const NeverScrollableScrollPhysics(), // 禁止滚动
        ),
      ),
    );
  }
}

 

posted @ 2022-05-13 17:37  rogerwu  阅读(70)  评论(0编辑  收藏  举报