mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: scroll to bottom when create new card
This commit is contained in:
parent
aba0f946dd
commit
d6162159aa
@ -198,7 +198,10 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
|
|
||||||
List<AFColumnItem> _buildRows(GroupPB group) {
|
List<AFColumnItem> _buildRows(GroupPB group) {
|
||||||
final items = group.rows.map((row) {
|
final items = group.rows.map((row) {
|
||||||
return BoardColumnItem(row: row, fieldId: group.fieldId);
|
return BoardColumnItem(
|
||||||
|
row: row,
|
||||||
|
fieldId: group.fieldId,
|
||||||
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
return <AFColumnItem>[...items];
|
return <AFColumnItem>[...items];
|
||||||
@ -286,17 +289,18 @@ class BoardColumnItem extends AFColumnItem {
|
|||||||
|
|
||||||
final String fieldId;
|
final String fieldId;
|
||||||
|
|
||||||
BoardColumnItem({required this.row, required this.fieldId});
|
final bool requestFocus;
|
||||||
|
|
||||||
|
BoardColumnItem({
|
||||||
|
required this.row,
|
||||||
|
required this.fieldId,
|
||||||
|
this.requestFocus = false,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get id => row.id;
|
String get id => row.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CreateCardItem extends AFColumnItem {
|
|
||||||
@override
|
|
||||||
String get id => '$CreateCardItem';
|
|
||||||
}
|
|
||||||
|
|
||||||
class GroupControllerDelegateImpl extends GroupControllerDelegate {
|
class GroupControllerDelegateImpl extends GroupControllerDelegate {
|
||||||
final AFBoardDataController controller;
|
final AFBoardDataController controller;
|
||||||
|
|
||||||
@ -304,10 +308,18 @@ class GroupControllerDelegateImpl extends GroupControllerDelegate {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void insertRow(GroupPB group, RowPB row, int? index) {
|
void insertRow(GroupPB group, RowPB row, int? index) {
|
||||||
final item = BoardColumnItem(row: row, fieldId: group.fieldId);
|
|
||||||
if (index != null) {
|
if (index != null) {
|
||||||
|
final item = BoardColumnItem(
|
||||||
|
row: row,
|
||||||
|
fieldId: group.fieldId,
|
||||||
|
);
|
||||||
controller.insertColumnItem(group.groupId, index, item);
|
controller.insertColumnItem(group.groupId, index, item);
|
||||||
} else {
|
} else {
|
||||||
|
final item = BoardColumnItem(
|
||||||
|
row: row,
|
||||||
|
fieldId: group.fieldId,
|
||||||
|
requestFocus: true,
|
||||||
|
);
|
||||||
controller.addColumnItem(group.groupId, item);
|
controller.addColumnItem(group.groupId, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'board_column/board_column.dart';
|
import 'board_column/board_column.dart';
|
||||||
@ -141,18 +143,22 @@ class AFBoardContent extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _AFBoardContentState extends State<AFBoardContent> {
|
class _AFBoardContentState extends State<AFBoardContent> {
|
||||||
|
late _BoardColumnState columnState;
|
||||||
|
|
||||||
final GlobalKey _columnContainerOverlayKey =
|
final GlobalKey _columnContainerOverlayKey =
|
||||||
GlobalKey(debugLabel: '$AFBoardContent overlay key');
|
GlobalKey(debugLabel: '$AFBoardContent overlay key');
|
||||||
late BoardOverlayEntry _overlayEntry;
|
late BoardOverlayEntry _overlayEntry;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
columnState = _BoardColumnState();
|
||||||
_overlayEntry = BoardOverlayEntry(
|
_overlayEntry = BoardOverlayEntry(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
final interceptor = OverlappingDragTargetInterceptor(
|
final interceptor = OverlappingDragTargetInterceptor(
|
||||||
reorderFlexId: widget.dataController.identifier,
|
reorderFlexId: widget.dataController.identifier,
|
||||||
acceptedReorderFlexId: widget.dataController.columnIds,
|
acceptedReorderFlexId: widget.dataController.columnIds,
|
||||||
delegate: widget.delegate,
|
delegate: widget.delegate,
|
||||||
|
columnKeys: UnmodifiableMapView(columnState.columnKeys),
|
||||||
);
|
);
|
||||||
|
|
||||||
final reorderFlex = ReorderFlex(
|
final reorderFlex = ReorderFlex(
|
||||||
@ -165,7 +171,7 @@ class _AFBoardContentState extends State<AFBoardContent> {
|
|||||||
dataSource: widget.dataController,
|
dataSource: widget.dataController,
|
||||||
direction: Axis.horizontal,
|
direction: Axis.horizontal,
|
||||||
interceptor: interceptor,
|
interceptor: interceptor,
|
||||||
children: _buildColumns(interceptor.columnKeys),
|
children: _buildColumns(),
|
||||||
);
|
);
|
||||||
|
|
||||||
return Stack(
|
return Stack(
|
||||||
@ -197,7 +203,7 @@ class _AFBoardContentState extends State<AFBoardContent> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildColumns(List<ColumnKey> columnKeys) {
|
List<Widget> _buildColumns() {
|
||||||
final List<Widget> children =
|
final List<Widget> children =
|
||||||
widget.dataController.columnDatas.asMap().entries.map(
|
widget.dataController.columnDatas.asMap().entries.map(
|
||||||
(item) {
|
(item) {
|
||||||
@ -222,21 +228,14 @@ class _AFBoardContentState extends State<AFBoardContent> {
|
|||||||
footBuilder: widget.footBuilder,
|
footBuilder: widget.footBuilder,
|
||||||
cardBuilder: widget.cardBuilder,
|
cardBuilder: widget.cardBuilder,
|
||||||
dataSource: dataSource,
|
dataSource: dataSource,
|
||||||
scrollController: ScrollController(),
|
scrollController: columnState.scrollController(columnData.id),
|
||||||
phantomController: widget.phantomController,
|
phantomController: widget.phantomController,
|
||||||
onReorder: widget.dataController.moveColumnItem,
|
onReorder: widget.dataController.moveColumnItem,
|
||||||
cornerRadius: widget.config.cornerRadius,
|
cornerRadius: widget.config.cornerRadius,
|
||||||
backgroundColor: widget.config.columnBackgroundColor,
|
backgroundColor: widget.config.columnBackgroundColor,
|
||||||
);
|
);
|
||||||
|
|
||||||
// columnKeys
|
columnState.cacheColumn(columnData.id, boardColumn.globalKey);
|
||||||
// .removeWhere((element) => element.columnId == columnData.id);
|
|
||||||
// columnKeys.add(
|
|
||||||
// ColumnKey(
|
|
||||||
// columnId: columnData.id,
|
|
||||||
// key: boardColumn.columnGlobalKey,
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
|
|
||||||
return ConstrainedBox(
|
return ConstrainedBox(
|
||||||
constraints: widget.columnConstraints,
|
constraints: widget.columnConstraints,
|
||||||
@ -297,3 +296,26 @@ class _BoardColumnDataSourceImpl extends AFBoardColumnDataDataSource {
|
|||||||
@override
|
@override
|
||||||
List<String> get acceptedColumnIds => dataController.columnIds;
|
List<String> get acceptedColumnIds => dataController.columnIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _BoardColumnState {
|
||||||
|
final Map<String, GlobalKey> columnKeys = {};
|
||||||
|
|
||||||
|
void cacheColumn(String columnId, GlobalKey key) {
|
||||||
|
columnKeys[columnId] = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollController scrollController(String columnId) {
|
||||||
|
final flexGlobalKey = columnKeys[columnId];
|
||||||
|
var scrollController = ScrollController();
|
||||||
|
if (flexGlobalKey != null) {
|
||||||
|
// assert(flexGlobalKey.currentWidget is ReorderFlex);
|
||||||
|
|
||||||
|
// if (flexGlobalKey.currentWidget is ReorderFlex) {
|
||||||
|
// final reorderFlex = flexGlobalKey.currentWidget as ReorderFlex;
|
||||||
|
// final offset = reorderFlex.scrollController!.offset;
|
||||||
|
// scrollController = ScrollController(initialScrollOffset: offset);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
return scrollController;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -88,7 +88,9 @@ class AFBoardColumnWidget extends StatefulWidget {
|
|||||||
|
|
||||||
final Color backgroundColor;
|
final Color backgroundColor;
|
||||||
|
|
||||||
const AFBoardColumnWidget({
|
final GlobalKey globalKey = GlobalKey();
|
||||||
|
|
||||||
|
AFBoardColumnWidget({
|
||||||
Key? key,
|
Key? key,
|
||||||
this.headerBuilder,
|
this.headerBuilder,
|
||||||
this.footBuilder,
|
this.footBuilder,
|
||||||
@ -114,10 +116,13 @@ class _AFBoardColumnWidgetState extends State<AFBoardColumnWidget> {
|
|||||||
final GlobalKey _columnOverlayKey =
|
final GlobalKey _columnOverlayKey =
|
||||||
GlobalKey(debugLabel: '$AFBoardColumnWidget overlay key');
|
GlobalKey(debugLabel: '$AFBoardColumnWidget overlay key');
|
||||||
|
|
||||||
|
late GlobalObjectKey _indexGlobalKey;
|
||||||
|
|
||||||
late BoardOverlayEntry _overlayEntry;
|
late BoardOverlayEntry _overlayEntry;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
_indexGlobalKey = GlobalObjectKey(widget.key!);
|
||||||
_overlayEntry = BoardOverlayEntry(
|
_overlayEntry = BoardOverlayEntry(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
final children = widget.dataSource.columnData.items
|
final children = widget.dataSource.columnData.items
|
||||||
@ -138,7 +143,6 @@ class _AFBoardColumnWidgetState extends State<AFBoardColumnWidget> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Widget reorderFlex = ReorderFlex(
|
Widget reorderFlex = ReorderFlex(
|
||||||
key: widget.key,
|
|
||||||
scrollController: widget.scrollController,
|
scrollController: widget.scrollController,
|
||||||
config: widget.config,
|
config: widget.config,
|
||||||
onDragStarted: (index) {
|
onDragStarted: (index) {
|
||||||
@ -161,6 +165,8 @@ class _AFBoardColumnWidgetState extends State<AFBoardColumnWidget> {
|
|||||||
children: children,
|
children: children,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
reorderFlex = KeyedSubtree(key: _indexGlobalKey, child: reorderFlex);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
margin: widget.margin,
|
margin: widget.margin,
|
||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
@ -172,10 +178,7 @@ class _AFBoardColumnWidgetState extends State<AFBoardColumnWidget> {
|
|||||||
children: [
|
children: [
|
||||||
if (header != null) header,
|
if (header != null) header,
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Padding(
|
child: Padding(padding: widget.itemMargin, child: reorderFlex),
|
||||||
padding: widget.itemMargin,
|
|
||||||
child: reorderFlex,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
if (footer != null) footer,
|
if (footer != null) footer,
|
||||||
],
|
],
|
||||||
|
@ -39,7 +39,7 @@ class ReorderDragTarget<T extends DragTargetData> extends StatefulWidget {
|
|||||||
final Widget child;
|
final Widget child;
|
||||||
final T dragTargetData;
|
final T dragTargetData;
|
||||||
|
|
||||||
final GlobalObjectKey _indexGlobalKey;
|
final GlobalObjectKey indexGlobalKey;
|
||||||
|
|
||||||
/// Called when dragTarget is being dragging.
|
/// Called when dragTarget is being dragging.
|
||||||
final DragTargetOnStarted onDragStarted;
|
final DragTargetOnStarted onDragStarted;
|
||||||
@ -69,9 +69,10 @@ class ReorderDragTarget<T extends DragTargetData> extends StatefulWidget {
|
|||||||
|
|
||||||
final bool useMoveAnimation;
|
final bool useMoveAnimation;
|
||||||
|
|
||||||
ReorderDragTarget({
|
const ReorderDragTarget({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.child,
|
required this.child,
|
||||||
|
required this.indexGlobalKey,
|
||||||
required this.dragTargetData,
|
required this.dragTargetData,
|
||||||
required this.onDragStarted,
|
required this.onDragStarted,
|
||||||
required this.onDragEnded,
|
required this.onDragEnded,
|
||||||
@ -82,8 +83,7 @@ class ReorderDragTarget<T extends DragTargetData> extends StatefulWidget {
|
|||||||
this.onAccept,
|
this.onAccept,
|
||||||
this.onLeave,
|
this.onLeave,
|
||||||
this.draggableTargetBuilder,
|
this.draggableTargetBuilder,
|
||||||
}) : _indexGlobalKey = GlobalObjectKey(child.key!),
|
}) : super(key: key);
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ReorderDragTarget<T>> createState() => _ReorderDragTargetState<T>();
|
State<ReorderDragTarget<T>> createState() => _ReorderDragTargetState<T>();
|
||||||
@ -112,7 +112,7 @@ class _ReorderDragTargetState<T extends DragTargetData>
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
dragTarget = KeyedSubtree(key: widget._indexGlobalKey, child: dragTarget);
|
dragTarget = KeyedSubtree(key: widget.indexGlobalKey, child: dragTarget);
|
||||||
return dragTarget;
|
return dragTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ class _ReorderDragTargetState<T extends DragTargetData>
|
|||||||
child: widget.child,
|
child: widget.child,
|
||||||
),
|
),
|
||||||
onDragStarted: () {
|
onDragStarted: () {
|
||||||
_draggingFeedbackSize = widget._indexGlobalKey.currentContext?.size;
|
_draggingFeedbackSize = widget.indexGlobalKey.currentContext?.size;
|
||||||
widget.onDragStarted(
|
widget.onDragStarted(
|
||||||
widget.child,
|
widget.child,
|
||||||
widget.dragTargetData.draggingIndex,
|
widget.dragTargetData.draggingIndex,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@ -55,13 +56,14 @@ class OverlappingDragTargetInterceptor extends DragTargetInterceptor {
|
|||||||
final String reorderFlexId;
|
final String reorderFlexId;
|
||||||
final List<String> acceptedReorderFlexId;
|
final List<String> acceptedReorderFlexId;
|
||||||
final OverlapDragTargetDelegate delegate;
|
final OverlapDragTargetDelegate delegate;
|
||||||
final List<ColumnKey> columnKeys = [];
|
final UnmodifiableMapView<String, GlobalKey> columnKeys;
|
||||||
Timer? _delayOperation;
|
Timer? _delayOperation;
|
||||||
|
|
||||||
OverlappingDragTargetInterceptor({
|
OverlappingDragTargetInterceptor({
|
||||||
required this.delegate,
|
required this.delegate,
|
||||||
required this.reorderFlexId,
|
required this.reorderFlexId,
|
||||||
required this.acceptedReorderFlexId,
|
required this.acceptedReorderFlexId,
|
||||||
|
required this.columnKeys,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -105,12 +107,6 @@ class OverlappingDragTargetInterceptor extends DragTargetInterceptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ColumnKey {
|
|
||||||
String columnId;
|
|
||||||
GlobalKey key;
|
|
||||||
ColumnKey({required this.columnId, required this.key});
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class CrossReorderFlexDragTargetDelegate {
|
abstract class CrossReorderFlexDragTargetDelegate {
|
||||||
/// * [reorderFlexId] is the id that the [ReorderFlex] passed in.
|
/// * [reorderFlexId] is the id that the [ReorderFlex] passed in.
|
||||||
bool acceptNewDragTargetData(
|
bool acceptNewDragTargetData(
|
||||||
|
@ -74,7 +74,7 @@ class ReorderFlex extends StatefulWidget {
|
|||||||
|
|
||||||
final DragTargetInterceptor? interceptor;
|
final DragTargetInterceptor? interceptor;
|
||||||
|
|
||||||
const ReorderFlex({
|
ReorderFlex({
|
||||||
Key? key,
|
Key? key,
|
||||||
this.scrollController,
|
this.scrollController,
|
||||||
required this.dataSource,
|
required this.dataSource,
|
||||||
@ -85,7 +85,9 @@ class ReorderFlex extends StatefulWidget {
|
|||||||
this.onDragEnded,
|
this.onDragEnded,
|
||||||
this.interceptor,
|
this.interceptor,
|
||||||
this.direction = Axis.vertical,
|
this.direction = Axis.vertical,
|
||||||
}) : super(key: key);
|
}) : assert(children.every((Widget w) => w.key != null),
|
||||||
|
'All child must have a key.'),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ReorderFlex> createState() => ReorderFlexState();
|
State<ReorderFlex> createState() => ReorderFlexState();
|
||||||
@ -112,10 +114,13 @@ class ReorderFlexState extends State<ReorderFlex>
|
|||||||
|
|
||||||
late ReorderFlexNotifier _notifier;
|
late ReorderFlexNotifier _notifier;
|
||||||
|
|
||||||
|
late Map<String, GlobalObjectKey> _childKeys;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_notifier = ReorderFlexNotifier();
|
_notifier = ReorderFlexNotifier();
|
||||||
dragState = DraggingState(widget.reorderFlexId);
|
dragState = DraggingState(widget.reorderFlexId);
|
||||||
|
_childKeys = {};
|
||||||
|
|
||||||
_animation = DragTargetAnimation(
|
_animation = DragTargetAnimation(
|
||||||
reorderAnimationDuration: widget.config.reorderAnimationDuration,
|
reorderAnimationDuration: widget.config.reorderAnimationDuration,
|
||||||
@ -159,7 +164,11 @@ class ReorderFlexState extends State<ReorderFlex>
|
|||||||
|
|
||||||
for (int i = 0; i < widget.children.length; i += 1) {
|
for (int i = 0; i < widget.children.length; i += 1) {
|
||||||
Widget child = widget.children[i];
|
Widget child = widget.children[i];
|
||||||
children.add(_wrap(child, i));
|
final item = widget.dataSource.items[i];
|
||||||
|
|
||||||
|
final indexGlobalKey = GlobalObjectKey(child.key!);
|
||||||
|
_childKeys[item.id] = indexGlobalKey;
|
||||||
|
children.add(_wrap(child, i, indexGlobalKey));
|
||||||
|
|
||||||
// if (widget.config.useMovePlaceholder) {
|
// if (widget.config.useMovePlaceholder) {
|
||||||
// children.add(DragTargeMovePlaceholder(
|
// children.add(DragTargeMovePlaceholder(
|
||||||
@ -168,6 +177,9 @@ class ReorderFlexState extends State<ReorderFlex>
|
|||||||
// ));
|
// ));
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
Future.delayed(Duration(seconds: 3), () {
|
||||||
|
scrollToBottom();
|
||||||
|
});
|
||||||
|
|
||||||
final child = _wrapContainer(children);
|
final child = _wrapContainer(children);
|
||||||
return _wrapScrollView(child: child);
|
return _wrapScrollView(child: child);
|
||||||
@ -203,10 +215,10 @@ class ReorderFlexState extends State<ReorderFlex>
|
|||||||
|
|
||||||
/// [child]: the child will be wrapped with dartTarget
|
/// [child]: the child will be wrapped with dartTarget
|
||||||
/// [childIndex]: the index of the child in a list
|
/// [childIndex]: the index of the child in a list
|
||||||
Widget _wrap(Widget child, int childIndex) {
|
Widget _wrap(Widget child, int childIndex, GlobalObjectKey indexGlobalKey) {
|
||||||
return Builder(builder: (context) {
|
return Builder(builder: (context) {
|
||||||
final ReorderDragTarget dragTarget =
|
final ReorderDragTarget dragTarget =
|
||||||
_buildDragTarget(context, child, childIndex);
|
_buildDragTarget(context, child, childIndex, indexGlobalKey);
|
||||||
int shiftedIndex = childIndex;
|
int shiftedIndex = childIndex;
|
||||||
|
|
||||||
if (dragState.isOverlapWithPhantom()) {
|
if (dragState.isOverlapWithPhantom()) {
|
||||||
@ -312,10 +324,15 @@ class ReorderFlexState extends State<ReorderFlex>
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReorderDragTarget _buildDragTarget(
|
ReorderDragTarget _buildDragTarget(
|
||||||
BuildContext builderContext, Widget child, int dragTargetIndex) {
|
BuildContext builderContext,
|
||||||
|
Widget child,
|
||||||
|
int dragTargetIndex,
|
||||||
|
GlobalObjectKey indexGlobalKey,
|
||||||
|
) {
|
||||||
final ReoderFlexItem reorderFlexItem =
|
final ReoderFlexItem reorderFlexItem =
|
||||||
widget.dataSource.items[dragTargetIndex];
|
widget.dataSource.items[dragTargetIndex];
|
||||||
return ReorderDragTarget<FlexDragTargetData>(
|
return ReorderDragTarget<FlexDragTargetData>(
|
||||||
|
indexGlobalKey: indexGlobalKey,
|
||||||
dragTargetData: FlexDragTargetData(
|
dragTargetData: FlexDragTargetData(
|
||||||
draggingIndex: dragTargetIndex,
|
draggingIndex: dragTargetIndex,
|
||||||
reorderFlexId: widget.reorderFlexId,
|
reorderFlexId: widget.reorderFlexId,
|
||||||
@ -515,6 +532,34 @@ class ReorderFlexState extends State<ReorderFlex>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scrollToBottom() {
|
||||||
|
if (_scrolling) return;
|
||||||
|
|
||||||
|
if (widget.dataSource.items.isNotEmpty) {
|
||||||
|
final item = widget.dataSource.items.last;
|
||||||
|
final indexKey = _childKeys[item.id];
|
||||||
|
if (indexKey == null) return;
|
||||||
|
|
||||||
|
final indexContext = indexKey.currentContext;
|
||||||
|
if (indexContext == null) return;
|
||||||
|
if (_scrollController.hasClients == false) return;
|
||||||
|
|
||||||
|
final renderObject = indexContext.findRenderObject();
|
||||||
|
if (renderObject != null) {
|
||||||
|
_scrolling = true;
|
||||||
|
_scrollController.position
|
||||||
|
.ensureVisible(
|
||||||
|
renderObject,
|
||||||
|
alignment: 0.5,
|
||||||
|
duration: const Duration(milliseconds: 120),
|
||||||
|
)
|
||||||
|
.then((value) {
|
||||||
|
setState(() => _scrolling = false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Scrolls to a target context if that context is not on the screen.
|
// Scrolls to a target context if that context is not on the screen.
|
||||||
void _scrollTo(BuildContext context) {
|
void _scrollTo(BuildContext context) {
|
||||||
if (_scrolling) return;
|
if (_scrolling) return;
|
||||||
|
Loading…
Reference in New Issue
Block a user