chore: repalce sliver header with single scroll view

This commit is contained in:
appflowy 2022-04-15 15:41:55 +08:00
parent d71e0de8c3
commit 6dbb708991
6 changed files with 93 additions and 53 deletions

View File

@ -1,3 +1,4 @@
import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
@ -7,13 +8,14 @@ import 'grid_service.dart';
part 'grid_header_bloc.freezed.dart';
class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
// final FieldService _fieldService;
final FieldService _fieldService;
final GridFieldCache fieldCache;
GridHeaderBloc({
required String gridId,
required this.fieldCache,
}) : super(GridHeaderState.initial(fieldCache.clonedFields)) {
}) : _fieldService = FieldService(gridId: gridId),
super(GridHeaderState.initial(fieldCache.clonedFields)) {
on<GridHeaderEvent>(
(event, emit) async {
await event.map(
@ -23,6 +25,7 @@ class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
emit(state.copyWith(fields: value.fields));
},
moveField: (_MoveField value) {},
);
},
);
@ -46,6 +49,7 @@ class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
class GridHeaderEvent with _$GridHeaderEvent {
const factory GridHeaderEvent.initial() = _InitialHeader;
const factory GridHeaderEvent.didReceiveFieldUpdate(List<Field> fields) = _DidReceiveFieldUpdate;
const factory GridHeaderEvent.moveField(int fromIndex, int toIndex) = _MoveField;
}
@freezed

View File

@ -1,21 +1,28 @@
import 'package:flutter/material.dart';
import 'package:linked_scroll_controller/linked_scroll_controller.dart';
class GridScrollController {
final ScrollController _verticalController = ScrollController();
final ScrollController _horizontalController = ScrollController();
final LinkedScrollControllerGroup _scrollGroupContorller;
final ScrollController verticalController;
final ScrollController horizontalController;
ScrollController get verticalController => _verticalController;
ScrollController get horizontalController => _horizontalController;
final List<ScrollController> _linkHorizontalControllers = [];
GridScrollController();
GridScrollController({required LinkedScrollControllerGroup scrollGroupContorller})
: _scrollGroupContorller = scrollGroupContorller,
verticalController = ScrollController(),
horizontalController = scrollGroupContorller.addAndGet();
// final SelectionChangeCallback? onSelectionChanged;
// final ShouldApplySelection? shouldApplySelection;
// final ScrollCallback? onScroll;
ScrollController linkHorizontalController() {
final controller = _scrollGroupContorller.addAndGet();
_linkHorizontalControllers.add(controller);
return controller;
}
void dispose() {
for (final controller in _linkHorizontalControllers) {
controller.dispose();
}
verticalController.dispose();
horizontalController.dispose();
}

View File

@ -9,6 +9,7 @@ import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Field;
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter/material.dart';
import 'package:linked_scroll_controller/linked_scroll_controller.dart';
import 'controller/grid_scroll.dart';
import 'layout/layout.dart';
import 'layout/sizes.dart';
@ -73,17 +74,23 @@ class FlowyGrid extends StatefulWidget {
}
class _FlowyGridState extends State<FlowyGrid> {
final _scrollController = GridScrollController();
final _scrollController = GridScrollController(scrollGroupContorller: LinkedScrollControllerGroup());
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocBuilder<GridBloc, GridState>(
buildWhen: (previous, current) => previous.fields.length != current.fields.length,
builder: (context, state) {
final contentWidth = GridLayout.headerWidth(state.fields);
final child = _wrapScrollView(
state.fields,
contentWidth,
[
_GridHeader(gridId: state.gridId, fields: state.fields),
const _GridRows(),
const _GridFooter(),
],
@ -91,6 +98,7 @@ class _FlowyGridState extends State<FlowyGrid> {
return Column(children: [
const _GridToolbarAdaptor(),
_gridHeader(context, state.gridId, contentWidth),
Flexible(child: child),
]);
},
@ -98,7 +106,7 @@ class _FlowyGridState extends State<FlowyGrid> {
}
Widget _wrapScrollView(
List<Field> fields,
double contentWidth,
List<Widget> slivers,
) {
final verticalScrollView = ScrollConfiguration(
@ -111,7 +119,7 @@ class _FlowyGridState extends State<FlowyGrid> {
);
final sizedVerticalScrollView = SizedBox(
width: GridLayout.headerWidth(fields),
width: contentWidth,
child: verticalScrollView,
);
@ -128,6 +136,19 @@ class _FlowyGridState extends State<FlowyGrid> {
child: horizontalScrollView,
);
}
Widget _gridHeader(BuildContext context, String gridId, double contentWidth) {
final fieldCache = context.read<GridBloc>().fieldCache;
return SizedBox(
width: contentWidth,
child: GridHeaderSliverAdaptor(
gridId: gridId,
fieldCache: fieldCache,
anchorScrollController: _scrollController.linkHorizontalController(),
),
);
}
}
class _GridToolbarAdaptor extends StatelessWidget {
@ -149,18 +170,6 @@ class _GridToolbarAdaptor extends StatelessWidget {
}
}
class _GridHeader extends StatelessWidget {
final String gridId;
final List<Field> fields;
const _GridHeader({Key? key, required this.gridId, required this.fields}) : super(key: key);
@override
Widget build(BuildContext context) {
final fieldCache = context.read<GridBloc>().fieldCache;
return GridHeaderSliverAdaptor(gridId: gridId, fieldCache: fieldCache);
}
}
class _GridRows extends StatefulWidget {
const _GridRows({Key? key}) : super(key: key);

View File

@ -13,25 +13,41 @@ import 'package:reorderables/reorderables.dart';
import 'field_editor.dart';
import 'field_cell.dart';
class GridHeaderSliverAdaptor extends StatelessWidget {
class GridHeaderSliverAdaptor extends StatefulWidget {
final String gridId;
final GridFieldCache fieldCache;
final ScrollController anchorScrollController;
const GridHeaderSliverAdaptor({
required this.gridId,
required this.fieldCache,
required this.anchorScrollController,
Key? key,
}) : super(key: key);
const GridHeaderSliverAdaptor({required this.gridId, required this.fieldCache, Key? key}) : super(key: key);
@override
State<GridHeaderSliverAdaptor> createState() => _GridHeaderSliverAdaptorState();
}
class _GridHeaderSliverAdaptorState extends State<GridHeaderSliverAdaptor> {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) =>
getIt<GridHeaderBloc>(param1: gridId, param2: fieldCache)..add(const GridHeaderEvent.initial()),
getIt<GridHeaderBloc>(param1: widget.gridId, param2: widget.fieldCache)..add(const GridHeaderEvent.initial()),
child: BlocBuilder<GridHeaderBloc, GridHeaderState>(
buildWhen: (previous, current) => previous.fields.length != current.fields.length,
builder: (context, state) {
return SliverPersistentHeader(
delegate: SliverHeaderDelegateImplementation(gridId: gridId, fields: state.fields),
floating: true,
pinned: true,
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
controller: widget.anchorScrollController,
child: SizedBox(height: GridSize.headerHeight, child: _GridHeader(gridId: widget.gridId)),
);
// return SliverPersistentHeader(
// delegate: SliverHeaderDelegateImplementation(gridId: gridId, fields: state.fields),
// floating: true,
// pinned: true,
// );
},
),
);
@ -46,7 +62,7 @@ class SliverHeaderDelegateImplementation extends SliverPersistentHeaderDelegate
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
return _GridHeader(gridId: gridId, fields: fields);
return _GridHeader(gridId: gridId);
}
@override
@ -66,13 +82,7 @@ class SliverHeaderDelegateImplementation extends SliverPersistentHeaderDelegate
class _GridHeader extends StatefulWidget {
final String gridId;
final List<Field> fields;
const _GridHeader({
Key? key,
required this.gridId,
required this.fields,
}) : super(key: key);
const _GridHeader({Key? key, required this.gridId}) : super(key: key);
@override
State<_GridHeader> createState() => _GridHeaderState();
@ -93,15 +103,17 @@ class _GridHeaderState extends State<_GridHeader> {
return Container(
color: theme.surface,
child: ReorderableRow(
crossAxisAlignment: CrossAxisAlignment.stretch,
scrollController: ScrollController(),
header: const _CellLeading(),
footer: _CellTrailing(gridId: widget.gridId),
onReorder: (int oldIndex, int newIndex) {
Log.info("from $oldIndex to $newIndex");
},
children: cells,
child: RepaintBoundary(
child: ReorderableRow(
crossAxisAlignment: CrossAxisAlignment.stretch,
scrollController: ScrollController(),
header: const _CellLeading(),
footer: _CellTrailing(gridId: widget.gridId),
onReorder: (int oldIndex, int newIndex) {
Log.info("from $oldIndex to $newIndex");
},
children: cells,
),
),
);
},

View File

@ -653,6 +653,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "4.4.0"
linked_scroll_controller:
dependency: "direct main"
description:
name: linked_scroll_controller
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
lint:
dependency: transitive
description:

View File

@ -75,6 +75,7 @@ dependencies:
fluttertoast: ^8.0.8
table_calendar: ^3.0.5
reorderables:
linked_scroll_controller: ^0.2.0
dev_dependencies:
flutter_lints: ^1.0.0