flutter bloc:LinkedScrollPosition 一旦创建就无法更改控制器

问题描述 投票:0回答:1

在我的 flutter 应用程序中,我想创建一个时间表小部件,它将以相应的标题水平和垂直滚动。时间表应将“日”作为水平标题,将“期间”作为垂直标题。我使用 linked_scroll_controller 来实现这一点。我使用 flutter bloc 作为状态管理。时间表按我的预期工作正常,但是当我更改屏幕方向(即屏幕旋转时)并出现以下错误时出现问题。

======== Exception caught by widgets library =======================================================
The following assertion was thrown building SingleChildScrollView(dependencies: [Directionality]):
_LinkedScrollPosition cannot change controllers once created.
'package:linked_scroll_controller/linked_scroll_controller.dart':
Failed assertion: line 142 pos 12: 'linkedPosition.owner == this'

The relevant error-causing widget was: 
SingleChildScrollView SingleChildScrollView:
When the exception was thrown, this was the stack: 
#2      _LinkedScrollController.attach (package:linked_scroll_controller/linked_scroll_controller.dart:142:12)
#3      ScrollableState.didUpdateWidget (package:flutter/src/widgets/scrollable.dart:561:34)
#4      StatefulElement.update (package:flutter/src/widgets/framework.dart:5142:55)
#5      Element.updateChild (package:flutter/src/widgets/framework.dart:3660:15)

下面是我的代码:

import 'package:linked_scroll_controller/linked_scroll_controller.dart';
import '../../time_table.dart';

class MyTimeTable extends StatefulWidget {
  final SchoolClass selClass;

  MyTimeTable({Key? key, required this.selClass}) : super(key: key);

  @override
  State<MyTimeTable> createState() => _MyTimeTableState();
}

class _MyTimeTableState extends State<MyTimeTable> {
  late LinkedScrollControllerGroup _horizontalControllersGroup;
  late ScrollController _horizontalBody;
  late ScrollController _horizontalHeader;
  late LinkedScrollControllerGroup _verticalControllersGroup;
  late ScrollController _verticalBody;
  late ScrollController _verticalHeader;

  List<dynamic>? periodList;
  List<dynamic>? timeTableList;
  final List<String> rowEntries = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday",];

  @override
  Widget build(BuildContext context) {

   context.read<ClassBloc>().add(FetchPeriodTimeTable(widget.classId));

    _horizontalControllersGroup = LinkedScrollControllerGroup();
    _horizontalBody = _horizontalControllersGroup.addAndGet();
    _horizontalHeader = _horizontalControllersGroup.addAndGet();
    _verticalControllersGroup = LinkedScrollControllerGroup();
    _verticalBody = _verticalControllersGroup.addAndGet();
    _verticalHeader = _verticalControllersGroup.addAndGet();

    return MaterialApp(
      home: Scaffold(
        resizeToAvoidBottomInset: false,
        appBar: sizedAppBar,
        body: SafeArea(
          child: Container(
            child: Column(
              children: [
                Row(
                  children: <Widget>[
                    SizedBox(height: cellHeight,width: cellWidth,...),
                    Expanded(
                      child: Container(// horizontal day header
                        height: 65,
                        width: 400,
                        child: SingleChildScrollView(
                          scrollDirection: Axis.horizontal,
                          controller: _horizontalHeader,
                          child: HeaderContainer(rowEntries: rowEntries),
                        ),
                      ),
                    )
                  ],
                ),
                Expanded(
                  child: Container(
                    child: Row(
                      children: <Widget>[
                        Container(// vertical period header
                          width: 100,
                          child: SingleChildScrollView(
                            controller: _verticalHeader,
                            child: getColumnContainer(),
                          ),
                        ),
                        Expanded( // data grid
                          child: SingleChildScrollView(
                            controller: _verticalBody,
                            child: SingleChildScrollView(
                              scrollDirection: Axis.horizontal,
                              controller: _horizontalBody,
                              child: getBodyContainer(),
                            ),
                          ),
                        )
                      ],
                    ),
                  ),
                ),
              ],
            ),

          ),
        ),
      ),
    );
  }
  

getColumnContainer() { // vertical period header
    return BlocBuilder<ClassBloc, ClassState>(
    builder: (context, state) {
        if(state is PeriodTimeTableList) {
        periodList = state.item1MultiList;
        }
        if(periodList != null) {
        int numberOfRows = periodList!.length;
        return ColumnContainer(
            colEntries: periodList!,
        );
        }
        return const SizedBox();
    },
    );
}

getBodyContainer() {
    return BlocBuilder<ClassBloc, ClassState>(
    builder: (context, state) {
        if(state is PeriodTimeTableList) {
        periodList = state.item1MultiList;
        timeTableList = state.item2MultiList;
        }
        if(periodList != null && timeTableList != null) {
        int _numberOfColumns = rowEntries.length;
        int _numberOfLines = periodList!.length;
        int itemCounter = 0;
        return BodyContainer(
            rowEntries: rowEntries,
            colEntries: periodList!,
            dataList: timeTableList!,
        );
        }
        return SizedBox();
    },
    );
}
    
}

颤振集团:

class ClassBloc extends Bloc<ClassEvent, ClassState> {
    final MyApi myApi;

    ClassBloc({required this.myApi}) : super(ClassInitial()) {
        
        on<FetchPeriodTimeTable>((event, emit) async {
        var result = await myApi.getPeriodTimeTable(event.classId);
        List<dynamic> periodList = [];
        periodList = result['periodList'];
        List<dynamic> timeTableList = [];
        timeTableList = result['timeTableList'];
        emit(PeriodTimeTableList(item1MultiList: periodList,item2MultiList: timeTableList));
        });
    }

    Future<void> updateTimeTable(TimeTable timeTable) async {
        try {   // to save add/edit function and update the list
        var result = await myApi.updateTimeTable(timeTable);
        if(result['status'] == 1) {
            List<dynamic> periodList = [];
            periodList = result['periodList'];
            List<dynamic> timeTableList = [];
            timeTableList = result['timeTableList'];
            emit(const TimeTableCreated());
            emit(PeriodTimeTableList(item1MultiList: periodList,item2MultiList: timeTableList));
        } else if(result['index'] == 2) {
            emit(const TimeTableNotCreated());
        } else {
            emit(const ErrorDialog(title: 'Sorry',message: 'Something went wrong'));
        }
        } catch (error) {
        emit(const ErrorDialog(title: 'Sorry',message: 'Something went wrong'));
        }
    }
}
flutter dart scrollview bloc state-management
1个回答
0
投票

您应该为每个使用 scrollcontroller 的小部件添加一个唯一的键

© www.soinside.com 2019 - 2024. All rights reserved.