Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow overwriting the NavigationAppBar Layout #708

Open
fischerscode opened this issue Jan 29, 2023 · 4 comments · May be fixed by #709
Open

Allow overwriting the NavigationAppBar Layout #708

fischerscode opened this issue Jan 29, 2023 · 4 comments · May be fixed by #709
Labels
enhancement New feature or request

Comments

@fischerscode
Copy link
Contributor

Is your feature request related to a problem? Please describe.
I want to implement some custom layout for the NavigationAppBar.

Describe the solution you'd like
It would be nice if NavigationAppBar would take an optional builder, in order to allow overwriting this behavior:

switch (displayMode) {
case PaneDisplayMode.top:
result = Row(children: [
leading,
if (additionalLeading != null) additionalLeading!,
title,
if (appBar.actions != null) Expanded(child: appBar.actions!)
]);
break;
case PaneDisplayMode.minimal:
case PaneDisplayMode.open:
case PaneDisplayMode.compact:
result = Stack(children: [
Align(
alignment: AlignmentDirectional.centerStart,
child: Row(mainAxisSize: MainAxisSize.min, children: [
leading,
if (additionalLeading != null) additionalLeading!,
Flexible(child: title),
]),
),
if (appBar.actions != null)
PositionedDirectional(
start: 0,
end: 0.0,
top: 0.0,
bottom: 0.0,
child: Align(
alignment: AlignmentDirectional.topEnd,
child: appBar.actions!,
),
),
]);
break;
default:
return const SizedBox.shrink();
}

Describe alternatives you've considered
The NavigationAppBar could also have a build-like method instead of the builder. For building a custom design, one could extend NavigationAppBar and override the build method.

Additional context
I want the design shown in the screenshot.
The MyApp should never overlay the Hamburger Icon and the Close button should fill the corner.
Additionally there should be a DragToMoveArea stacked behind the Row.
grafik

@fischerscode fischerscode linked a pull request Jan 29, 2023 that will close this issue
3 tasks
@bdlukaa
Copy link
Owner

bdlukaa commented Jan 31, 2023

The title widget should take the whole app bar. actions, on the other hand, will be drawn on top of the title.

You can perform this layout by providing the desired layout to the title property

@fischerscode
Copy link
Contributor Author

fischerscode commented Jan 31, 2023

I think I tried this and it resulted in a white bar at the right side of the red button.

I'll retry it tomorrow.

@fischerscode
Copy link
Contributor Author

fischerscode commented Feb 2, 2023

TLDR;
By using title and action and manually accounting for the actions width, my goal seems to be achievable, but I don't think it's an elegant solution and it still has a limitation.

Using actions

grafik
grafik
The CommandBarCard is in front of the leading Button. ❌

Code
import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter_acrylic/flutter_acrylic.dart' as flutter_acrylic;
import 'package:window_manager/window_manager.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await flutter_acrylic.Window.initialize();
  await WindowManager.instance.ensureInitialized();
  windowManager.waitUntilReadyToShow(
    const WindowOptions(
      minimumSize: Size(350, 600),
      center: true,
      titleBarStyle: TitleBarStyle.hidden,
      fullScreen: false,
    ),
    () async {
      await windowManager.show();
      await windowManager.setPreventClose(false);
      await windowManager.focus();
    },
  );

  runApp(FluentApp(
    debugShowCheckedModeBanner: false,
    home: NavigationView(
      appBar: NavigationAppBar(
          actions: Row(
        children: [
          Expanded(
              child: CommandBarCard(
            child: CommandBar(
                mainAxisAlignment: MainAxisAlignment.end,
                crossAxisAlignment: CrossAxisAlignment.center,
                primaryItems: [
                  CommandBarButton(onPressed: () {}, label: Text("Button1")),
                  CommandBarButton(onPressed: () {}, label: Text("Button2")),
                  CommandBarButton(onPressed: () {}, label: Text("Button3")),
                  CommandBarButton(onPressed: () {}, label: Text("Button4")),
                ]),
          )),
          SizedBox(
            width: 138,
            height: 50,
            child: WindowCaption(
              backgroundColor: Colors.transparent,
            ),
          ),
        ],
      )),
      pane: NavigationPane(items: []),
    ),
  ));
}

Using title

grafik
The red close button is not in the corner. ❌

Code
import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter_acrylic/flutter_acrylic.dart' as flutter_acrylic;
import 'package:window_manager/window_manager.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await flutter_acrylic.Window.initialize();
  await WindowManager.instance.ensureInitialized();
  windowManager.waitUntilReadyToShow(
    const WindowOptions(
      minimumSize: Size(350, 600),
      center: true,
      titleBarStyle: TitleBarStyle.hidden,
      fullScreen: false,
    ),
    () async {
      await windowManager.show();
      await windowManager.setPreventClose(false);
      await windowManager.focus();
    },
  );

  runApp(FluentApp(
    debugShowCheckedModeBanner: false,
    home: NavigationView(
      appBar: NavigationAppBar(
          title: Row(
        children: [
          Expanded(
              child: CommandBarCard(
            child: CommandBar(
                mainAxisAlignment: MainAxisAlignment.end,
                crossAxisAlignment: CrossAxisAlignment.center,
                primaryItems: [
                  CommandBarButton(onPressed: () {}, label: Text("Button1")),
                  CommandBarButton(onPressed: () {}, label: Text("Button2")),
                  CommandBarButton(onPressed: () {}, label: Text("Button3")),
                  CommandBarButton(onPressed: () {}, label: Text("Button4")),
                ]),
          )),
          SizedBox(
            width: 138,
            height: 50,
            child: WindowCaption(
              backgroundColor: Colors.transparent,
            ),
          ),
        ],
      )),
      pane: NavigationPane(items: []),
    ),
  ));
}

Using title and action

grafik
Title and actions are stacked on top of each other. ❌

Code
import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter_acrylic/flutter_acrylic.dart' as flutter_acrylic;
import 'package:window_manager/window_manager.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await flutter_acrylic.Window.initialize();
  await WindowManager.instance.ensureInitialized();
  windowManager.waitUntilReadyToShow(
    const WindowOptions(
      minimumSize: Size(350, 600),
      center: true,
      titleBarStyle: TitleBarStyle.hidden,
      fullScreen: false,
    ),
    () async {
      await windowManager.show();
      await windowManager.setPreventClose(false);
      await windowManager.focus();
    },
  );

  runApp(FluentApp(
    debugShowCheckedModeBanner: false,
    home: NavigationView(
      appBar: NavigationAppBar(
        title: Expanded(
            child: CommandBarCard(
          child: CommandBar(
              mainAxisAlignment: MainAxisAlignment.end,
              crossAxisAlignment: CrossAxisAlignment.center,
              primaryItems: [
                CommandBarButton(onPressed: () {}, label: Text("Button1")),
                CommandBarButton(onPressed: () {}, label: Text("Button2")),
                CommandBarButton(onPressed: () {}, label: Text("Button3")),
                CommandBarButton(onPressed: () {}, label: Text("Button4")),
              ]),
        )),
        actions: SizedBox(
          width: 138,
          height: 50,
          child: WindowCaption(
            backgroundColor: Colors.transparent,
          ),
        ),
      ),
      pane: NavigationPane(items: []),
    ),
  ));
}

Using title and action and manually accounting for the actions width

grafik
Actually works, I did not think about this solution earlier, but I don't think this solution is elegant. ✅

Code
import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter_acrylic/flutter_acrylic.dart' as flutter_acrylic;
import 'package:window_manager/window_manager.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await flutter_acrylic.Window.initialize();
  await WindowManager.instance.ensureInitialized();
  windowManager.waitUntilReadyToShow(
    const WindowOptions(
      minimumSize: Size(350, 600),
      center: true,
      titleBarStyle: TitleBarStyle.hidden,
      fullScreen: false,
    ),
    () async {
      await windowManager.show();
      await windowManager.setPreventClose(false);
      await windowManager.focus();
    },
  );

  runApp(FluentApp(
    debugShowCheckedModeBanner: false,
    home: NavigationView(
      appBar: NavigationAppBar(
        title: Row(
          children: [
            Expanded(
                child: CommandBarCard(
              child: CommandBar(
                  mainAxisAlignment: MainAxisAlignment.end,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  primaryItems: [
                    CommandBarButton(onPressed: () {}, label: Text("Button1")),
                    CommandBarButton(onPressed: () {}, label: Text("Button2")),
                    CommandBarButton(onPressed: () {}, label: Text("Button3")),
                    CommandBarButton(onPressed: () {}, label: Text("Button4")),
                  ]),
            )),
            SizedBox(width: 138),
          ],
        ),
        actions: SizedBox(
          width: 138,
          height: 50,
          child: WindowCaption(
            backgroundColor: Colors.transparent,
          ),
        ),
      ),
      pane: NavigationPane(items: []),
    ),
  ));
}
Disadvantage about this solution: It's not possible to add a `DragToMoveArea` that triggers when the user drags at the marked area. ❌ This would be possible with #709.

grafik

@bdlukaa
Copy link
Owner

bdlukaa commented May 29, 2023

On the native side, the title always go behind the window features (title and actions). But I also agree that there is a "search bar" (or something related) in some native UWP apps

This is a hard problem to solve, because desktop aims adaptability of different window sizes, otherwise it can cause to some weird effects. Here is a screenshot of "Slack" with a small size:

image

On the other hand, on Task Manager, the "search bar" window feature works differently. If there isn't enough space, the bar is changed to a button:

Before / Small

After / Big

Differently, Microsoft Store just resizes to the minimum size and keep the search bar functionality:

image

But, after it all, none of the above is described in the Win UI documentation. In fact, the only option Microsoft provides to add some custom content is either:

  • AutoSuggestBox
  • PaneCustomContent, a property that displays some content after the pane items

image


I like the idea of having a possibility to add a custom functionality to the top bar, but this is not something that can be built-in the package. I will stand the point that the title property can be used to display such things, since a LayoutBuilder can be used to achieve adaptability.

I don't think this can be implemented into the package because there isn't a strict documentation about it, so the developers will need to invent the desired behavior themselves. In fact, not even the window buttons (minimize, maximize/resume, close) are provided by the package, since it's not in the documentation.

@bdlukaa bdlukaa added the enhancement New feature or request label Nov 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants