Flutter两个ListView同步滚动。

界面布局:第一层是左右结构, 左边只能上下滑动, 右边既可以水平滑动又可以上下滑动, 而且左边和右边的上下滑动同步。

其中包含ListView去掉边界水波纹的设置。

这里先添加Google开发团队开发的依赖库 linked_scroll_controller 。

dependencies:
  flutter:
    sdk: flutter

  flutter_localizations:
    sdk: flutter

  linked_scroll_controller: ^0.2.0

完整代码如下

import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:linked_scroll_controller/linked_scroll_controller.dart';
// import 'package:my_main/common/util/base_util.dart';

void main() {
  // BaseUtil.logToConsole('main_begin');

  //如果size是0, 则设置回调, 在回调中runApp。
  if (window.physicalSize.isEmpty) {
    window.onMetricsChanged = () {
      //在回调中, size仍然有可能是0。
      if (!window.physicalSize.isEmpty) {
        window.onMetricsChanged = null;
        runApp(MyApp());
      }
    };
  } else {
    //如果size非0, 则直接runApp。
    runApp(MyApp());
  }

  // BaseUtil.logToConsole('main_end');
}

class MyApp extends StatelessWidget {
  MyApp({Key? key}) : super(key: key) {
    // BaseUtil.logToConsole('MyApp');
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('ScrollView'),
        ),
        backgroundColor: const Color(0xfff3f3f3),
        //body占屏幕的大部分。
        body: const MyScrollWidget(),
      ),
    );
  }
}

class MyScrollWidget extends StatefulWidget {
  const MyScrollWidget({super.key});

  @override
  State<StatefulWidget> createState() => _MyScrollWidgetState();
}

class _MyScrollWidgetState extends State<MyScrollWidget> {
  static const double _textRowH = 40.0;
  static const double _leftRowSeparatorH = 1.0;
  static const int _leftRowCount = 23;
  late LinkedScrollControllerGroup _controllers;
  late ScrollController _controllerForL;
  late ScrollController _controllerForR;

  @override
  void dispose() {
    _controllerForL.dispose();
    _controllerForR.dispose();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();
    _controllers = LinkedScrollControllerGroup();
    _controllerForL = _controllers.addAndGet();
    _controllerForR = _controllers.addAndGet();
  }

  /// 注: Flutter中的ScrollView是抽象类, 因此不能直接用来创建对象。
  /// Flutter也提供了它的子类, 如 ListView、PageView、GridView、CustomScrollView 。
  /// 下面的布局:第一层是左右结构, 左边只能上下滑动, 右边既可以水平滑动又可以上下滑动, 而且左边和右边的上下滑动同步。
  @override
  Widget build(BuildContext context) {
    // 注: MediaQuery.of(context).size 要放在build中调用。
    final boxSize = MediaQuery.of(context).size;
    const mainLeftViewW = 80.0;
    return Row(
      children: [
        _buildMainLeftView(mainLeftViewW),
        _buildMainRightView(boxSize.width + 200),
      ],
    );
  }

  Widget _buildMainLeftView(double width) {
    return Container(
      width: width,
      color: const Color(0xfff0f0f0),
      child: ListView.separated(
        controller: _controllerForL,
        itemCount: _leftRowCount,
        itemBuilder: (BuildContext context, int index) {
          return Container(
            height: _textRowH,
            alignment: Alignment.centerLeft,
            child: Text('左侧栏-行' + (index + 1).toString()),
          );
        },
        separatorBuilder: (BuildContext context, int index) {
          return Container(
              height: _leftRowSeparatorH, color: const Color(0xff999999));
        },
      ),
    );
  }

  Widget _buildMainRightView(double contentW) {
    const double eachSpaceH = (_textRowH * (_leftRowCount - 3) +
            _leftRowSeparatorH * (_leftRowCount - 1)) /
        2.0;
    return Expanded(
      flex: 1,
      child: ListView(
        scrollDirection: Axis.horizontal,
        children: [
          SizedBox(
            width: contentW,
            child: ListView(
              controller: _controllerForR,
              children: [
                SizedBox(
                  height: _textRowH,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: const [
                      Text('== == == BeginLeft == == =='),
                      Text('== == == BeginRight == == =='),
                    ],
                  ),
                ),
                const SizedBox(height: eachSpaceH),
                const SizedBox(
                  height: _textRowH,
                  child: Text('== == == 既可以水平滑动又可以上下滑动 == == =='),
                ),
                const SizedBox(height: eachSpaceH),
                const SizedBox(
                  height: _textRowH,
                  child: Text(
                    '== == == End == == ==',
                    textAlign: TextAlign.center,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

/// ListView去掉边界水波纹, 使用示例:
///   ScrollConfiguration(
///     behavior: MyScrollBehavior(),
///     child: ListView.builder( . . . ),
///   );
class MyScrollBehavior extends ScrollBehavior {
  @override
  Widget buildOverscrollIndicator(
      BuildContext context, Widget child, ScrollableDetails details) {
    switch (getPlatform(context)) {
      case TargetPlatform.iOS:
        return child;
      case TargetPlatform.android:
      case TargetPlatform.fuchsia:
        return GlowingOverscrollIndicator(
          child: child,
          // 不显示头部水波纹
          showLeading: false,
          // 不显示尾部水波纹
          showTrailing: false,
          axisDirection: details.direction,
          color: Colors.red,
        );
      case TargetPlatform.linux:
        break;
      case TargetPlatform.macOS:
        break;
      case TargetPlatform.windows:
        break;
    }
    return child;
  }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值