-
-
Notifications
You must be signed in to change notification settings - Fork 504
Description
Problem Description
When building a frameless window application using TabView as the main UI component, there's currently no clean way to make the TabView header area draggable for window movement. This is a common requirement for modern desktop applications that want to provide window dragging functionality through the tab bar area.
Currently, to achieve window dragging through the TabView header, developers need to use invasive workarounds that involve:
- Manipulating the TabView's internal widget structure through
stripBuilder - Wrapping components with custom drag detection widgets
- Complex logic to differentiate between tab dragging and window dragging
Current Workaround (Invasive Implementation)
Here's the current approach I'm using, which demonstrates the complexity and invasiveness of the solution:
import 'package:fluent_ui/fluent_ui.dart';
import 'package:window_manager/window_manager.dart';
// Custom drag region widget
class CustomDragRegion extends StatelessWidget {
final Widget? child;
final HitTestBehavior behavior;
const CustomDragRegion({
super.key,
this.child,
this.behavior = HitTestBehavior.translucent,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onPanStart: (details) {
windowManager.startDragging();
},
behavior: behavior,
child: child ?? SizedBox.expand(child: Container(color: Colors.transparent)),
);
}
}
// Usage in TabView - requires complex stripBuilder manipulation
TabView(
tabs: tabs,
stripBuilder: (context, stripWidget) {
if (stripWidget is! Row) return stripWidget;
// Complex logic to wrap the strip with drag region
// while preserving tab functionality
return CustomDragRegion(child: stripWidget);
},
header: CustomDragRegion(
child: SizedBox(
width: 50.0,
child: Container(color: Colors.transparent),
),
),
)Proposed Solution
Add built-in support for window dragging in TabView through one of these approaches:
Option 1: Add onDragStart callback to TabView
TabView(
tabs: tabs,
onDragStart: (details) {
// Custom drag handling (e.g., window dragging)
windowManager.startDragging();
},
)Option 2: Add dragRegionBuilder callback
TabView(
tabs: tabs,
dragRegionBuilder: (context, child) {
return GestureDetector(
onPanStart: (details) => windowManager.startDragging(),
child: child,
);
},
)Benefits
- Cleaner API: Eliminates the need for complex
stripBuildermanipulations - Better maintainability: Reduces coupling between window management and UI structure
- Improved developer experience: Provides a standard way to implement this common pattern
- Performance: Avoids unnecessary widget tree manipulations
Use Cases
- Desktop applications with frameless windows
- Modern UI designs where the tab bar serves as the title bar
- Applications that need custom window dragging behavior
- Cross-platform desktop apps using Flutter
Additional Context
This feature would be particularly valuable for desktop Flutter applications using packages like window_manager or bitsdojo_window for custom window management. The current workaround is functional but requires deep knowledge of TabView's internal structure and is fragile to future changes.
Longshot20250727015227.mov
Environment
- Flutter version: Channel stable, 3.32.1, on macOS 15.5 24F74 darwin-arm64, locale zh-Hans-CN
- fluent_ui version: 4.12.0
- Platform: Desktop (Windows/macOS/Linux)