flutter desktop macos でウィンドウ透明にしたり色々するぞー
はじめに
flutterのデスクトップを作るにあたって透明なウィンドウが欲しかったのでウィンドウのスタイルをいじる方法を調べたり実装したりした。 あと上記にあたって、blurのぼかし具合が微妙だったので調整できたら楽しそうだなーと思って色々調べてたけど無理っぽそうなので諦めた、というお話。人生。
サンプル
こちら、以下を設定できる
- ウィンドウの影
- 透過ウィンドウ
- blur
- 背景色rgbaで設定
- こんなかんじ
- 実際はこんなにインタラクティブな動きをする必要ないと思うので
AppDelegate
にapplicationDidFinishLaunching
を追加して任意の項目をコピペすればいいかなあという所感
やったことなど
flutterのwidgetの背景色を透明にするだけではだめで、プラットフォーム側でウィンドウを透明にするなりなんなりしてやる必要がある。 多分不透明なウィンドウの上にflutterのwidgetが乗ってるイメージ。widgetが透明でも透過した後ろの要素が不透明なのでだめですよってお話。 なので透過したかったらプラットフォーム側で定義してく。
swiftを書け
具体的には extension NSWindow
で任意のメソッドを追加して、FlutterMethodChannel
経由で呼び出す。それだーけ。
該当箇所は
github.com
と github.com らへん
flutter側はいい塩梅にinvokeMethod
から対象のメソッド呼ぶ感じ
Future<void> _invokeMethod(String method, Map<String, dynamic> arg) async { await platform.invokeMethod(method, arg); } Future<void> _setBlur() async { await _invokeMethod("blur", <String, dynamic>{ "blur": _blur, }); }
かんたんですね
補遺
なおカラーピッカーは flex_color_picker
という神パッケージがあったのでこちらを利用。ありがたい
対象OS
flutter desktop macos で色々頑張ったというお話なのでそれ以外のことは何もわからない。
windows, linuxは↓のパッケージで良いと思う。 pub.dev
課題
macosはblurの透過度を変更できないっぽいので前述のパッケージで言う aero
, acrylic
のような変更ができないっぽそうなので実現方法を模索した
以下なんとなくモヤモヤしてるけど諦めたことと試したこと
blurが地味
ダークテーマのblurが地味。 背景が同系色だったらblurかかってるのかどうかよくわからない具合のぼかし度合い。 なのでぼかし度をなんとかして調整できないかな〜〜と思って試行錯誤などをした(結果ダメだった)。
以下とても有益な情報
NSVisualEffectViewのblurのRadiusは変更できない.
— Kyome𓃠 (@Kyomesuke) 2020年4月18日
↓は無理やり使うとリジェクトされるって話っぽそう?(なのでこの段階で諦めた)
Translucent NSWindow with blurred background · GitHub
個人的なアプリを作る過程で今回の一連のアレコレをしているだけで、ストア通したりする予定はないけど、個人的なアプリなので若干気に食わないけど無理やり頑張る必要もないんだよなーと思って考えるのをやめた。
stackoverflowでアニメーションを途中で止めたらそれっぽいみたいな話もあったけどiosの話だったのでそのままは適用できなかった。
UIBlurEffect
があるんやからNSBlurEffect
もあってくれ。
swift - How to edit the UIBlurEffect intensity? - Stack Overflow
以下な感じで一応アニメーションを試したけれどだめだた。 普通に透過風味になる。
self.isOpaque = false self.backgroundColor = .clear let contentView = contentViewController!.view let superView = contentView.superview! let blurView = NSVisualEffectView() blurView.frame = superView.bounds blurView.autoresizingMask = [.width, .height] blurView.blendingMode = NSVisualEffectView.BlendingMode.behindWindow blurView.material = NSVisualEffectView.Material.underWindowBackground let views = contentView.subviews let view = views.first! contentView.subviews = [blurView] blurView.addSubview(view) // animation let basicAnimation = CABasicAnimation(keyPath: "opacity") basicAnimation.fromValue = 1 basicAnimation.toValue = 0.0 basicAnimation.duration = 10.0 // NSThemeFrame superView.layer?.add(basicAnimation, forKey: "opacity") superView.layer?.opacity = 0.5 // FlutterViewWrapper contentView.layer?.add(basicAnimation, forKey: "opacity") contentView.layer?.opacity = 0.5 // NSVisualEffectView blurView.layer?.add(basicAnimation, forKey: "opacity") blurView.layer?.opacity = 0.5
その他試したこと
NSImageViewで半透明画像を利用してCIFilterのblur使ったりもしたけどalpha値をいじるのとほとんど見た目からわなかったからやめた。若干濃淡あるくらいでopacityのグラデーションくらいにしかならなそう。ぼかしたいのよこっちは。
おわりに
flutterで遊んでるつもりがずっとswift書いてるな? blur関連で知見ある方いたら教えて下さい。 また、当方がflutterでお仕事をしたいそうで、こちらが本稿の最も重要な内容となります。 flutterのお仕事ください。