Closed lucasjinreal closed 2 years ago
Did you follow the installation instructions and modify the MainFlutterWindow.swift
file as described? Also, did you get any warnings in your console output?
@Adrian-Samoticha thank u sir! Soved it.
btw, may I ask one more question? Do u know is there a way to add a left column which is fully blurred the the right is the content like this:
What you can do is define the sidebar as a transparent SizedBox
of fixed width (assuming its width should not be modifiable by the user) that is placed to the left of the opaque content view using the Row
widget. Now call the following code inside your initState()
method:
Window.makeTitlebarTransparent();
Window.enableFullSizeContentView();
Window.hideTitle();
Window.setEffect(effect: WindowEffect.sidebar);
This way, the sidebar, and the content view occupy the entirety of the window. You should now place the TitlebarSafeArea
widget inside the sidebar so that only its content is affected by it.
You will get something that looks like this:
This is the entire main.dart
file for the example I have just described:
EDIT: The code above is outdated. See https://github.com/alexmercerind/flutter_acrylic/issues/32#issuecomment-1479311482
thanks a ton! will try it out!
@Adrian-Samoticha Hello, I tried your code on windows, this is only what I got,:
how can I have a move windows bar in the left, which is tint, while a opaque window bar on the right?
@Adrian-Samoticha I got only like this when hiden titlebar:
class MyHomePageDesktop extends StatefulWidget {
const MyHomePageDesktop({Key? key}) : super(key: key);
@override
State<MyHomePageDesktop> createState() => _MyHomePageDesktopState();
}
class _MyHomePageDesktopState extends State<MyHomePageDesktop> {
@override
void initState() {
Window.makeTitlebarTransparent();
Window.enableFullSizeContentView();
Window.hideTitle();
Window.setEffect(effect: WindowEffect.sidebar, dark: false);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
body: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_generateSidebar(),
Column(
children: [
Expanded(
child: Row(
children: [
WindowTitleBar(
brightness: InterfaceBrightness.dark,
),
],
),
),
Expanded(
child: _generateContentView(),
)
],
),
],
),
);
}
Widget _generateSidebar() {
return TitlebarSafeArea(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 8.0),
child: Text(
'sidebar',
style: TextStyle(
color: Colors.white,
),
),
),
);
}
DecoratedBox _generateContentView() {
return const DecoratedBox(
decoration: BoxDecoration(
color: Color.fromRGBO(64, 64, 64, 1.0),
border: Border(
left: BorderSide(
color: Color.fromRGBO(0, 0, 0, 0.35),
),
),
),
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text(
'content view',
style: TextStyle(
color: Colors.white,
),
),
),
);
}
}
enum InterfaceBrightness {
light,
dark,
auto,
}
extension InterfaceBrightnessExtension on InterfaceBrightness {
bool getIsDark(BuildContext context) {
if (this == InterfaceBrightness.light) return false;
if (this == InterfaceBrightness.auto) {
if (context == null) return true;
return MediaQuery.of(context).platformBrightness == Brightness.dark;
}
return true;
}
Color getForegroundColor(BuildContext context) {
return getIsDark(context) ? Colors.white : Colors.black;
}
}
class WindowTitleBar extends StatelessWidget {
final InterfaceBrightness brightness;
const WindowTitleBar({Key? key, required this.brightness}) : super(key: key);
@override
Widget build(BuildContext context) {
return Platform.isWindows
? Container(
width: MediaQuery.of(context).size.width,
height: 32.0,
color: Colors.transparent,
child: MoveWindow(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Container(),
),
MinimizeWindowButton(
colors: WindowButtonColors(
iconNormal: brightness == InterfaceBrightness.light
? Colors.black
: Colors.white,
iconMouseDown: brightness == InterfaceBrightness.light
? Colors.black
: Colors.white,
iconMouseOver: brightness == InterfaceBrightness.light
? Colors.black
: Colors.white,
normal: Colors.transparent,
mouseOver: brightness == InterfaceBrightness.light
? Colors.black.withOpacity(0.04)
: Colors.white.withOpacity(0.04),
mouseDown: brightness == InterfaceBrightness.light
? Colors.black.withOpacity(0.08)
: Colors.white.withOpacity(0.08),
),
),
MaximizeWindowButton(
colors: WindowButtonColors(
iconNormal: brightness == InterfaceBrightness.light
? Colors.black
: Colors.white,
iconMouseDown: brightness == InterfaceBrightness.light
? Colors.black
: Colors.white,
iconMouseOver: brightness == InterfaceBrightness.light
? Colors.black
: Colors.white,
normal: Colors.transparent,
mouseOver: brightness == InterfaceBrightness.light
? Colors.black.withOpacity(0.04)
: Colors.white.withOpacity(0.04),
mouseDown: brightness == InterfaceBrightness.light
? Colors.black.withOpacity(0.08)
: Colors.white.withOpacity(0.08),
),
),
CloseWindowButton(
onPressed: () {
appWindow.close();
},
colors: WindowButtonColors(
iconNormal: brightness == InterfaceBrightness.light
? Colors.black
: Colors.white,
iconMouseDown: brightness == InterfaceBrightness.light
? Colors.black
: Colors.white,
iconMouseOver: brightness == InterfaceBrightness.light
? Colors.black
: Colors.white,
normal: Colors.transparent,
mouseOver: brightness == InterfaceBrightness.light
? Colors.black.withOpacity(0.04)
: Colors.white.withOpacity(0.04),
mouseDown: brightness == InterfaceBrightness.light
? Colors.black.withOpacity(0.08)
: Colors.white.withOpacity(0.08),
),
),
],
),
),
)
: Container();
}
}
@jinfagang Ah, I see. window_plus might offer what you're after.
@Adrian-Samoticha hi, thanks, how to combine window-plugs and acrylic to get the desired effect people usually need?
@jinfagang Frankly, I don't really know. I only maintain the macOS port and have never compiled a Flutter application for Windows before. Perhaps @alexmercerind can help you, instead.
@Adrian-Samoticha @alexmercerind Hello guys.
I now got very close:
the question is, the oriingla title bar seems not hiden at all even I force it:
@override
void initState() {
Window.makeTitlebarTransparent();
Window.hideWindowControls();
Window.enableFullSizeContentView();
Window.enableFullSizeContentView();
Window.hideTitle();
Window.setEffect(effect: WindowEffect.sidebar, dark: false);
super.initState();
}
And the to make the windowTitlebar not translucent but same color as Content view?
using the suggested code,, using TitleBarSafeArea always crashes the application with this error
macos_window_utils/MainFlutterWindowManipulator.swift:364: Fatal error: Unexpectedly found nil while unwrapping an Optional value
TitlebarSafeArea(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 8.0),
child: Text(
'sidebar',
style: TextStyle(
color: Colors.white,
),
),
),
),
I solved the issue by changing MainFlutterWindowManipulator.swift: as follows
let windowFrameHeight = (self.mainFlutterWindow?.contentView?.frame.height) ?? 0
let contentLayoutRectHeight = self.mainFlutterWindow?.contentLayoutRect.height ?? 0
let fullSizeContentViewNoContentAreaHeight = windowFrameHeight - contentLayoutRectHeight
return fullSizeContentViewNoContentAreaHeight
But the app I guess not handling the effects correctly
using the suggested code,, using TitleBarSafeArea always crashes the application with this error
macos_window_utils/MainFlutterWindowManipulator.swift:364: Fatal error: Unexpectedly found nil while unwrapping an Optional value
TitlebarSafeArea( child: Padding( padding: EdgeInsets.symmetric(horizontal: 8.0), child: Text( 'sidebar', style: TextStyle( color: Colors.white, ), ), ), ),
Did you follow the installation instructions? What does your MainFlutterWindow.swift
file look like?
Window.makeTitlebarTransparent(); Window.hideWindowControls(); Window.enableFullSizeContentView(); Window.enableFullSizeContentView(); Window.hideTitle(); Window.setEffect(effect: WindowEffect.sidebar, dark: false);
super.initState();
@Adrian-Samoticha appreciate the quick reply,,,
here is my MainFlutterWindow.swift
import macos_window_utils
import Cocoa
import FlutterMacOS
class MainFlutterWindow: NSWindow {
override func awakeFromNib() {
let flutterViewController = FlutterViewController.init()
let windowFrame = self.frame
self.contentViewController = flutterViewController
self.setFrame(windowFrame, display: true)
RegisterGeneratedPlugins(registry: flutterViewController)
super.awakeFromNib()
}
}
Window.makeTitlebarTransparent(); Window.hideWindowControls(); Window.enableFullSizeContentView(); Window.enableFullSizeContentView(); Window.hideTitle(); Window.setEffect(effect: WindowEffect.sidebar, dark: false);
super.initState();
@Adrian-Samoticha appreciate the quick reply,,,
here is my MainFlutterWindow.swift
import macos_window_utils import Cocoa import FlutterMacOS class MainFlutterWindow: NSWindow { override func awakeFromNib() { let flutterViewController = FlutterViewController.init() let windowFrame = self.frame self.contentViewController = flutterViewController self.setFrame(windowFrame, display: true) RegisterGeneratedPlugins(registry: flutterViewController) super.awakeFromNib() } }
You are still using
FlutterViewController
, but you need to useMacOSWindowUtilsViewController
instead. Also, it is important that you callMainFlutterWindowManipulator.start(mainFlutterWindow: self)
.
Make sure your code looks like this:
import Cocoa
import FlutterMacOS
import macos_window_utils
class MainFlutterWindow: NSWindow {
override func awakeFromNib() {
let windowFrame = self.frame
let macOSWindowUtilsViewController = MacOSWindowUtilsViewController()
self.contentViewController = macOSWindowUtilsViewController
self.setFrame(windowFrame, display: true)
/* Initialize the macos_window_utils plugin */
MainFlutterWindowManipulator.start(mainFlutterWindow: self)
RegisterGeneratedPlugins(registry: macOSWindowUtilsViewController.flutterViewController)
super.awakeFromNib()
}
}
Window.makeTitlebarTransparent(); Window.hideWindowControls(); Window.enableFullSizeContentView(); Window.enableFullSizeContentView(); Window.hideTitle(); Window.setEffect(effect: WindowEffect.sidebar, dark: false);
super.initState();
@Adrian-Samoticha appreciate the quick reply,,, here is my MainFlutterWindow.swift
import macos_window_utils import Cocoa import FlutterMacOS class MainFlutterWindow: NSWindow { override func awakeFromNib() { let flutterViewController = FlutterViewController.init() let windowFrame = self.frame self.contentViewController = flutterViewController self.setFrame(windowFrame, display: true) RegisterGeneratedPlugins(registry: flutterViewController) super.awakeFromNib() } }
You are still using
FlutterViewController
, but you need to useMacOSWindowUtilsViewController
instead. Also, it is important that you callMainFlutterWindowManipulator.start(mainFlutterWindow: self)
.Make sure your code looks like this:
import Cocoa import FlutterMacOS import macos_window_utils class MainFlutterWindow: NSWindow { override func awakeFromNib() { let windowFrame = self.frame let macOSWindowUtilsViewController = MacOSWindowUtilsViewController() self.contentViewController = macOSWindowUtilsViewController self.setFrame(windowFrame, display: true) /* Initialize the macos_window_utils plugin */ MainFlutterWindowManipulator.start(mainFlutterWindow: self) RegisterGeneratedPlugins(registry: macOSWindowUtilsViewController.flutterViewController) super.awakeFromNib() } }
amazing,, I thought I copied the same file,,, now it works fine
@Adrian-Samoticha Hello, Adrian, does macOS black background problem solved or not?
@Adrian-Samoticha Hello, Adrian, does macOS black background problem solved or not?
It is solved. Make sure you’re running the latest version of flutter_acrylic.
@Adrian-Samoticha But I try previous flutter_acrylic breaks windows, if I remember correctly
@Adrian-Samoticha But I try previous flutter_acrylic breaks windows, if I remember correctly
The issue was an accidental breaking change in macos_window_utils, not in flutter_acrylic. More specifically, I have moved a source file in macos_window_utils and it broke an import statement in flutter_acrylic, however, that was solvable by patching macos_window_utils without touching flutter_acrylic.
Honestly, the way Dart handles imports from third-party packages is quite odd. A package typically has a source file called <package_name>.dart
which exports all the libraries the package provides. However, dependents can still import files directly and there is no way to prevent that as a package author. This means that technically, any moved file is a breaking change by default, and refactoring your directory structure becomes impossible. Perhaps I should enable linter warnings in flutter_acrylic and patch the imports to prevent that from happening in the future, but in my opinion, this shouldn’t have occurred in the first place.
@Adrian-Samoticha How to add minmax button on the left?
@Adrian-Samoticha Looks like no window button if so::
By default, these buttons should be visible. You can call the showCloseButton
, showMiniaturize
, and showZoomButton
methods to show them if they are hidden.
@Adrian-Samoticha thanks, where should I call show these buttons in flutter_acrylic api?
I just noticed you are calling Window.hideWindowControls();
in the code you posted above. That’s the method call that hides your buttons. Don’t call it if you want the buttons to appear.
Also, the code I’ve posted above is outdated anyway. You should use the TransparentMacOSSidebar
widget if you are running the latest version of flutter_acrylic so that you can use wallpaper tinting in your windows:
import 'package:flutter/material.dart';
import 'package:flutter_acrylic/flutter_acrylic.dart';
import 'package:flutter_acrylic/widgets/transparent_macos_sidebar.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Window.initialize();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
Window.makeTitlebarTransparent();
Window.enableFullSizeContentView();
Window.hideTitle();
Window.setEffect(effect: WindowEffect.solid);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
body: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: const [
_Sidebar(),
Expanded(
child: _ContentView(),
),
],
),
);
}
}
class _ContentView extends StatelessWidget {
const _ContentView();
@override
Widget build(BuildContext context) {
return const DecoratedBox(
decoration: BoxDecoration(
border: Border(
left: BorderSide(
color: Color.fromRGBO(0, 0, 0, 0.35),
),
),
),
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text(
'content view',
style: TextStyle(
color: Colors.white,
),
),
),
);
}
}
class _Sidebar extends StatelessWidget {
const _Sidebar();
@override
Widget build(BuildContext context) {
return const TransparentMacOSSidebar(
child: SizedBox(
width: 192.0,
child: TitlebarSafeArea(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 8.0),
child: Text(
'sidebar',
style: TextStyle(
color: Colors.white,
),
),
),
),
),
);
}
}
thanks so much! BTW, does the same code can be used on windows? Or it must need sperated code for 2 platforms?
TransparentMacOSSidebar
doesn’t work on Windows. You will need to call the Window.setEffect
method with some transparent effect and make sure the content view has a non-transparent background color when targeting non-macOS platforms.
Hi, my project not fully using nullsafety. when intergate to my project, the window appear a second and crash, error:
do u know why?
I have init it:
the rest of the thing are exactly same on example app, the example app I can run it sucess.