bdlukaa / fluent_ui

Implements Microsoft's WinUI3 in Flutter.
https://bdlukaa.github.io/fluent_ui/
BSD 3-Clause "New" or "Revised" License
2.98k stars 465 forks source link

[Feature Request] Implement a Windows-styled reorderable list #845

Open harlanx opened 1 year ago

harlanx commented 1 year ago

Describe the bug When re-arranging the items with any fluent buttons in ReorderableListView.builder, it throws an assertion on AnimatedDefaultTextStyle

Additional context

Sample code ```dart ReorderableListView.builder( shrinkWrap: true, buildDefaultDragHandles: false, itemCount: numbers.length, onReorder: (oldIndex, newIndex) { setState(() { if (oldIndex < newIndex) { newIndex -= 1; } final int item = numbers.removeAt(oldIndex); numbers.insert(newIndex, item); }); }, itemBuilder: (context, index) { final number = numbers.elementAt(index); return ReorderableDragStartListener( key: ValueKey(index), index: index, child: number.isOdd ? ListTile( key: Key('$index'), // Fluent button tileColor: ButtonState.all(Colors.purple), leading: Button( onPressed: null, child: Text(number.toString()), ), title: Text(number.toString()), ) : ListTile( key: Key('$index'), // Material button tileColor: ButtonState.all(Colors.blue), leading: mt.TextButton( onPressed: null, child: Text(number.toString()), ), title: Text(number.toString()), ), ); }, ) ```
Debug ``` ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ The following assertion was thrown building AnimatedDefaultTextStyle(duration: 167ms, debugLabel: ((englishLike bodyMedium 2014).merge(whiteRedmond bodyMedium)).merge(unknown), inherit: false, color: Color(0xffffffff), family: Segoe UI, size: 14.0, weight: 400, baseline: alphabetic, decoration: TextDecoration.none, textAlign: center, softWrap: wrapping at box width, overflow: clip, dirty, state: _AnimatedDefaultTextStyleState#c44ab(ticker active)): Failed to interpolate TextStyles with different inherit values. The TextStyles being interpolated were: from: TextStyle(inherit: true, color: Color(0xffffffff), size: 14.0, weight: 400) to: TextStyle(debugLabel: ((englishLike bodyMedium 2014).merge(whiteRedmond bodyMedium)).merge(unknown), inherit: false, color: Color(0xffffffff), family: Segoe UI, size: 14.0, weight: 400, baseline: alphabetic, decoration: TextDecoration.none) The following fields are unspecified in both TextStyles: "backgroundColor", "letterSpacing", "wordSpacing", "height", "decorationColor", "decorationThickness". When "inherit" changes during the transition, these fields may observe abrupt value changes as a result, causing "jump"s in the transition. In general, TextStyle.lerp only works well when both TextStyles have the same "inherit" value, and specify the same fields. If the TextStyles were directly created by you, consider bringing them to parity to ensure a smooth transition. If one of the TextStyles being lerped is significantly more elaborate than the other, and has "inherited" set to false, it is often because it is merged with another TextStyle before being lerped. Comparing the "debugLabel"s of the two TextStyles may help identify if that was the case. For example, you may see this error message when trying to lerp between "ThemeData()" and "Theme.of(context)". This is because TextStyles from "Theme.of(context)" are merged with TextStyles from another theme and thus are more elaborate than the TextStyles from "ThemeData()" (which is reflected in their "debugLabel"s -- TextStyles from "Theme.of(context)" should have labels in the form of "().merge()"). It is recommended to only lerp ThemeData with matching TextStyles. The relevant error-causing widget was: AnimatedDefaultTextStyle AnimatedDefaultTextStyle:file:///C:/Users/Arctic%20Snow/AppData/Local/Pub/Cache/hosted/pub.dev/fluent_ui-4.6.1/lib/src/controls/inputs/buttons/base.dart:199:22 When the exception was thrown, this was the stack: #0 TextStyle.lerp. (package:flutter/src/painting/text_style.dart:1187:7) #1 TextStyle.lerp (package:flutter/src/painting/text_style.dart:1228:6) #2 TextStyleTween.lerp (package:flutter/src/widgets/implicit_animations.dart:214:41) #3 Tween.transform (package:flutter/src/animation/tween.dart:356:12) #4 Animatable.evaluate (package:flutter/src/animation/tween.dart:68:46) #5 _AnimatedDefaultTextStyleState.build (package:flutter/src/widgets/implicit_animations.dart:1961:22) #6 StatefulElement.build (package:flutter/src/widgets/framework.dart:5198:27) #7 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5086:15) #8 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5251:11) #9 Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7) #10 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2780:19) #11 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:903:21) #12 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:358:5) #13 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1284:15) #14 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1214:9) #15 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1072:5) #16 _invoke (dart:ui/hooks.dart:142:13) #17 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:359:5) #18 _drawFrame (dart:ui/hooks.dart:112:31) ════════════════════════════════════════════════════════════════════════════════════════════════════ Another exception was thrown: A RenderFlex overflowed by 98898 pixels on the right. Another exception was thrown: Failed to interpolate TextStyles with different inherit values. Another exception was thrown: Failed to interpolate TextStyles with different inherit values. Another exception was thrown: Failed to interpolate TextStyles with different inherit values. ```
harlanx commented 1 year ago

current workaround is wrapping any fluent button that are inside the ReorderableListView's itemBuilder with Material or FluentTheme widget.

bdlukaa commented 1 year ago

We currently export material's ReorderableListView. A proper solution would be to implement ReorderableList in the fluent-design.

A showcase of this can be found at winui3gallery://item/ListView

bdlukaa commented 1 year ago

This is the implementation of reordering in the native WinUI 3 Gallery.

https://github.com/bdlukaa/fluent_ui/assets/45696119/1898a492-a73a-4d02-b514-8efd0f0a6a34

I tried porting Flutter's ReorderableList to the Windows Style, but I faced a limitation. ReorderableList doesn't have the possibility to change the other widgets when one is being dragged, which is the main concept of the native reorderable list